2012-09-28 16 views
16

की विधि भेजें मैं send विधि को समझ नहीं पा रहा हूं। मैं समझता हूं कि इसका उपयोग जनरेटर को संचालित करने के लिए किया जाता है। लेकिन वाक्यविन्यास यहां है: generator.send(value)पायथन 3: जेनरेटर

मैं किसी भी तरह पकड़ नहीं सकता कि मूल्य वर्तमान yield अभिव्यक्ति का परिणाम क्यों बनना चाहिए।

def gen(): 
    for i in range(10): 
     X = yield i 
     if X == 'stop': 
      break 
     print("Inside the function " + str(X)) 

m = gen() 
print("1 Outside the function " + str(next(m)) + '\n') 
print("2 Outside the function " + str(next(m)) + '\n') 
print("3 Outside the function " + str(next(m)) + '\n') 
print("4 Outside the function " + str(next(m)) + '\n') 
print('\n') 
print("Outside the function " + str(m.send(None)) + '\n') # Start generator 
print("Outside the function " + str(m.send(77)) + '\n') 
print("Outside the function " + str(m.send(88)) + '\n') 
#print("Outside the function " + str(m.send('stop')) + '\n') 
print("Outside the function " + str(m.send(99)) + '\n') 
print("Outside the function " + str(m.send(None)) + '\n') 

परिणाम है::

1 Outside the function 0 

Inside the function None 
2 Outside the function 1 

Inside the function None 
3 Outside the function 2 

Inside the function None 
4 Outside the function 3 



Inside the function None 
Outside the function 4 

Inside the function 77 
Outside the function 5 

Inside the function 88 
Outside the function 6 

Inside the function 99 
Outside the function 7 

Inside the function None 
Outside the function 8 

ठीक है, स्पष्ट रूप से बोल रहा है, यह मेरे आश्चर्यजनक है मैं एक उदाहरण तैयार किया।

  1. प्रलेखन हम पढ़ सकते हैं कि जब एक yield बयान निष्पादित किया जाता है, जनरेटर के राज्य जमे हुए है और expression_list का मूल्य next के फोन करने वाले के लिए वापस आ जाता है। ठीक है, ऐसा प्रतीत नहीं होता है। हम gen() के अंदर if कथन और print फ़ंक्शन निष्पादित क्यों कर सकते हैं।
  2. मैं कैसे समझ सकता हूं कि X फ़ंक्शन के अंदर और बाहर क्यों भिन्न है? ठीक है। आइए मान लें कि send(77) 77 में m प्रसारित करता है। खैर, yield अभिव्यक्ति 77 हो जाती है। फिर X = yield i क्या है? और समारोह के अंदर 77 कैसे बाहर होता है जब बाहर होता है?
  3. पहला परिणाम स्ट्रिंग जनरेटर के अंदर जो भी हो रहा है उसे प्रतिबिंबित नहीं करती है?

वैसे भी, क्या आप किसी भी तरह इन send और yield कथन पर टिप्पणी कर सकते हैं?

उत्तर

40

जब आप जनरेटर में send और अभिव्यक्ति yield का उपयोग करते हैं, तो आप इसे कोरआउटिन के रूप में मान रहे हैं; निष्पादन का एक अलग धागा जो अनुक्रमिक रूप से interleaved चला सकते हैं लेकिन अपने कॉलर के साथ समानांतर में नहीं।

जब कॉलर R = m.send(a) निष्पादित करता है, तो यह जनरेटर के इनपुट स्लॉट में ऑब्जेक्ट a डालता है, जेनरेटर पर नियंत्रण स्थानांतरित करता है, और प्रतिक्रिया के लिए प्रतीक्षा करता है। जनरेटर को X = yield i के परिणामस्वरूप ऑब्जेक्ट प्राप्त करता है, और जब तक यह yield अभिव्यक्ति को हिट नहीं करता तब तक चलता है। Y = yield j। फिर यह j को अपने आउटपुट स्लॉट में रखता है, कॉलर को वापस नियंत्रण स्थानांतरित करता है, और तब तक प्रतीक्षा करता है जब तक कि इसे दोबारा शुरू नहीं किया जाता है। R = m.send(a) के परिणामस्वरूप कॉलर j प्राप्त करता है, और जब तक यह S = m.send(b) कथन को हिट नहीं करता तब तक चलता है।

R = next(m)R = m.send(None) जैसा ही है; यह जनरेटर के इनपुट स्लॉट में None डाल रहा है, इसलिए यदि जनरेटर X = yield i के परिणाम की जांच करता है तो XNone होगा।

Dumb waiter

जब सर्वर एक ग्राहक से एक आदेश हो जाता है, वे पैड गूंगा वेटर में डाल यह रसोई में send,, और से इंतजार:

एक रूपक के रूप में, एक dumb waiter पर विचार पकवान के लिए पक्षियों के बच्चे:

R = kitchen.send("Ham omelette, side salad") 

महाराज (है जो पक्षियों के बच्चे से इंतजार कर रहे थे) आदेश को चुनता है, पकवान तैयार करता है, yield रेस्तरां में यह है, और अगले आदेश के लिए इंतजार कर रहा है:

next_order = yield [HamOmelette(), SideSalad()] 

सर्वर (जो पक्षियों के बच्चे से इंतजार कर रहा है) क्योंकि send के बाद पक्षियों के बच्चे से दोनों सर्वर और महाराज इंतजार एक आदेश ing आदि किसी अन्य आदेश के ग्राहक और रिटर्न के लिए पकवान,

लेता है या yield एक पकवान में, केवल एक ही व्यक्ति किसी भी समय कुछ भी कर रहा है यानी प्रक्रिया एकल धागा है। दोनों पक्ष सामान्य नियंत्रण प्रवाह का उपयोग कर सकते हैं, क्योंकि जनरेटर मशीनरी (गूंगा वेटर) अंतःस्थापित निष्पादन की देखभाल करता है। ऊपर अधिक सरलीकृत कोड पर

+0

को मान असाइन। – jfs

+0

@ जेएफ। सेबेस्टियन मुझे लगता है कि "समवर्ती" का अर्थ समानांतर में है? – ecatmur

+2

प्रोग्रामिंग "समांतर" में "समवर्ती" का तात्पर्य है लेकिन सामान्य में विपरीत सत्य नहीं है। [समवर्ती प्रोग्रामिंग और समांतर प्रोग्रामिंग के बीच अंतर] (http://stackoverflow.com/q/1897993/4279) – jfs

4
def gen(): 
    i = 1 
    while True: 
     i += 1 
     x = yield i 
     print(x) 

m = gen() 
next(m) 
next(m) 
m.send(4) 

परिणाम

None 
4 

देखो।
मुझे लगता है कि आपके भ्रम की ओर अग्रसर चीज 'x = yield i' statment है, यह कथन यह नहीं कह रहा है कि मुझे भेजने के लिए भेजा गया मान() विधि से स्वीकार किया गया मान है, तो मैं x पर आंका गया हूं। इसके बजाय, जनरेटर को उपज स्टेटमेंट द्वारा मूल्य लौटाया जाता है, एक्स को भेजकर() विधि द्वारा assgined किया जाता है। एक कथन एक ही समय में दो चीजें करता है।

9

सबसे भ्रमित भाग यह लाइन X = yield i होना चाहिए, विशेष रूप से जब आप जेनरेटर पर send() पर कॉल करते हैं। वास्तव में केवल एक चीज आप को पता है की जरूरत है: next()send(None)

दुभाषिया स्तर में

के बराबर है:

शाब्दिक स्तर में

X = yield i (आदेश मामलों) लाइनों के नीचे करने के लिए बराबर होती है :

yield i 
# won't continue until next() or send() is called 
# and this is also the entry point of next() or send() 
X = the_input_of_send 

और, टिप्पणी की 2 पंक्तियां सटीक कारण हैं, हमें क्यों सीए की आवश्यकता है ll पहली बार के लिए send(None), क्योंकि जनरेटर वापस आ जाएगी i (उपज i) इससे पहले कि यह समवर्ती समानांतर में सिर्फ नहीं चलाता X

+0

महान उत्तर! सरल और आसान स्पष्टीकरण। आपने कमजोर बिंदु 'एक्स = उपज i' बहुत अच्छी तरह से पहचाना। 10 गुना ऊपर उठ जाएगा –

संबंधित मुद्दे