2013-04-10 10 views
7

चेतावनी: चरम नौसिखिया प्रश्नपाइथन में कोई फ़ंक्शन इसके मानों को याद करने के बाद कैसे याद करता है?

मैं एक नुस्खा के रूप में कार्यों के बारे में सोच रहा था। मेरी दुनिया में, कार्यक्रम एक नुस्खा बॉक्स है और कुछ व्यंजनों (कार्यों) अन्य व्यंजनों (अन्य कार्यों) के लिए कॉल करते हैं। प्रोसेसर रैम में निर्देश लिखकर और उनके माध्यम से काम करके मास्टर रेसिपी को निष्पादित करना शुरू कर देता है। नाश्ते के crepes की तरह। आप जूलिया चाइल्ड्स से नाश्ते के क्रीप्स रेसिपी को बुलाते हैं। आपको एक बार क्रेप बल्लेबाज बनाना है। फिर, जब भी आपके पास क्रेप बल्लेबाज होता है, तो आप इसे क्रेप्स बनाते हैं। समवर्ती रूप से, आप विभिन्न फल तैयार कर सकते हैं जो आप कर सकते हैं।

ठीक है, मैं स्पष्ट रूप से समझ में नहीं आता। मैंने pythontutor.com के माध्यम से प्रोजेक्ट यूलर Problem 2 (4 मिलियन से भी कम फाइबोनैकी संख्याओं का योग) के लिए पाइथन विकी समाधान चलाया। और मुझे लगता है कि मेरे साथ कुछ हुआ। ऐसा लगता है कि जब भी आप एक नुस्खा स्वीकार करते हैं, तो आप केवल उसी प्रोसेसर का उपयोग नहीं करते हैं, आपको उस फ़ंक्शन पर काम करने के लिए कुछ बर्तनों के साथ एक gnome मिलता है। बर्तन चर होते हैं, gnome अपनी नुस्खा का काम करता है, और, अगर कॉलिंग फ़ंक्शन वापसी मूल्यों की अपेक्षा कर रहा था, तो gnome कॉलर को उन बर्तनों की सामग्री दिखाता है। कॉलर फिर वापस जा सकता है, कुछ और चीजें समझ सकता है, और अपने कॉलर को रिटर्न वैल्यू दिखा सकता है।

तो आइए कहें अल अल बॉब को क्रेप्स बनाने के लिए कहते हैं। बॉब बल्लेबाज बनाता है और चार्ली को उन्हें पकाते हैं। चार्ली एक क्रेप बनाती है, बॉब को उस क्रेप परोसती है, बॉब इसे अल को देती है, और चार्ली वापस जाती है। कौन अभी भी मौजूद है! अल इस बात से अनजान है कि बॉब ने चार्ली को रसोई में रखा है, लेकिन चार्ली उस पहले क्रेप को बनाने के बाद भी, वह रसोईघर में है, जानता है कि एक क्रेप कैसे बनाना है, और जानता है कि उसने कितना क्रेप बल्लेबाज छोड़ा है। भले ही वह पहले ही क्रेप वापस कर चुका है।

क्या कोई इसे मेरे लिए साफ़ करने में मदद कर सकता है?

यहाँ अजगर विकी

def fib(): 
    x,y = 0,1 
    while True: 
     yield x 
     x,y = y, x+y 

def even(seq): 
    for number in seq: 
     if not number % 2: 
      yield number 

def under_a_million(seq): 
    for number in seq: 
     if number > 1000000: 
      break 
     yield number 

print sum(even(under_a_million(fib()))) 

से कोड है और यहाँ http://pythontutor.com/visualize.html

+6

आपका भ्रम समझ में आता है। कार्यक्रम 'उपज' कीवर्ड को छोड़कर, आपको लगता है कि उन्हें किस प्रकार (सॉर्ट) करना चाहिए। जैसा कि आप वर्णन करते हैं, 'उपज', सिंक के नीचे एक gnome स्टोर करता है। जबकि आप सीख रहे हैं तो आप 'उपज' से बचने का विकल्प चुन सकते हैं, या आप इसे विशेष रूप से पढ़ना चुन सकते हैं। –

+1

आपके पास * जेनरेटर * हैं। जनरेटर हर बार बर्फ पर डालते हैं जब वे 'उपज' कीवर्ड में आते हैं, जो उनके ऊपर लूपिंग पर नियंत्रण लौटाते हैं। –

+0

http://www.jeffknupp.com/blog/2013/02/14/drastically-improve-your-python-understanding-pythons-execution-model/ – Torxed

उत्तर

2

इसका कारण यह है उन कार्यों कार्यों नहीं हैं, लेकिन generators है। yield कथन एक मान देता है, लेकिन फ़ंक्शन से वापस नहीं आता है। प्रत्येक बार जब आप जनरेटर पर next पर कॉल करते हैं, तो यह जनरेटर को अंतिम कॉल से निष्पादित करता है, जब तक कि यह yield कथन तक पहुंच न जाए।

1

सिद्धांत रूप में आपकी पहली धारणा सही थी: फ़ंक्शन निष्पादित होने पर फ़ंक्शन के चर केवल तभी उपलब्ध होते हैं। हालांकि, आपके मामले में, आप yield कथन का उपयोग कर रहे हैं। नतीजतन फ़ंक्शन कॉल एक इटेटरेटर देता है, जिसे कॉल किया जाता है, अगले yield कथन का मान देता है।

this post जांचें कि यह क्या है और इसके बारे में और स्पष्टीकरण के लिए।

2

एक सरल उत्तर।

यदि आपके पास कोई ऐसा फ़ंक्शन है जो मानों का अनुक्रम उत्पन्न करता है, तो आप इसे उपज का उपयोग करके generator में बदल सकते हैं।

def func(): 
    for i in range(3): 
     yield i 

list(func()) ==> [0,1,2] 

for el in func(): 
    print(el) # 0 
       # 1 
       # 2 

हर बार उपज कहा जाता है कि फ़ंक्शन कहीं जमे हुए है। जब इसे फिर से बुलाया जाता है तो यह अपने अंतिम राज्य से जारी रहता है, और फिर से शुरू नहीं होता है (जब तक कि यह तत्वों का उपभोग करने के लिए समाप्त नहीं हो जाता)।

यदि आप फ़ंक्शन को कॉल करते हैं तो आपको generator मिलता है, जो कि आप फिर से शुरू कर सकते हैं।

ध्यान दें कि इस तरह आप असीमित स्मृति का उपयोग करने के बिना अनंत अनुक्रमों को फिर से शुरू कर सकते हैं।

def inf(): 
    x = -1 
    while True: 
     x = x + 1 
     yield x 

for i in inf(): 
    if i < 10: 
     print(i) 
    else: 
     break 
संबंधित मुद्दे