2011-09-22 15 views
6

कोड वार्ता अधिक:लैम्बडा फ़ंक्शन पायथन में पैरामीटर को बंद नहीं करता है?


from pprint import pprint 

li = [] 

for i in range(5): 
     li.append(lambda : pprint(i)) 

for k in li: 
     k() 

उपज:

 
4 
4 
4 
4 
4 

क्यों नहीं

 
0 
1 
2 
3 
4 

??

धन्यवाद।

पीएस अगर मैं पूरा डेकोरेटर बारे में, यह उम्मीद के रूप में काम करता है: केवल बजाय i

+0

देखें [यह प्रश्न] (http://stackoverflow.com/q/2295290/195823) और [इस प्रश्न का मेरा जवाब] (http://stackoverflow.com/questions/2295290/what-do-lambda- फ़ंक्शन-क्लोजर-कैप्चर-इन-पायथन/2295372 # 2295372) –

+0

आप देख सकते हैं कि मूल लूप को फ़ंक्शन में ले जाकर चर को बंद कर रहा है, और उसके बाद फ़ंक्शन को 'k के लिए li: 'लाइन से पहले कॉल करना है, इसलिए कि 'i' मॉड्यूल स्तर के दायरे में मान्य नाम नहीं है। यह अभी भी काम करेगा (और एक ही परिणाम प्राप्त करें क्योंकि यह एक संदर्भ को बंद नहीं कर रहा है), जिसका अर्थ है कि नाम बंद है। – agf

+0

आप सभी को धन्यवाद।मुझे लगता है कि http://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture-in-python/2295368#2295368 न केवल समाधान बताता है बल्कि क्यों। मुझे लगता है कि मेरा प्रश्न http://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture-in-python – Grissiom

उत्तर

10

आपको बस इतना करना बात यह है कि जब तक आपकी सूची पॉप्युलेट हो जाती है, तब तक i के पास अनुक्रम में आखिरी वस्तु को अनुक्रमित किया जाएगा जब पुनरावृत्ति समाप्त हो जाए, इसलिए यही कारण है कि आप 4 को देख रहे हैं।

3

के वर्तमान मूल्य यह ठीक से संदर्भ करता i कब्जा करने के लिए

lambda i=i: pprint(i) 

,:



from pprint import pprint 

li = [] 

#for i in range(5): 
     #li.append(lambda : pprint(i)) 

def closure(i): 
     def _func(): 
       pprint(i) 
     return _func 

for i in range(5): 
     li.append(closure(i)) 

for k in li: 
     k() 
0

लैम्ब्डा फ़ंक्शन i चर पर बंद कर देता है। पहले for लूप समाप्त होने के बाद, i का मूल्य 4 है।

फिर दूसरा for पाश शुरू होता है और सभी लैम्ब्डा फ़ंक्शंस निष्पादित होते हैं। उनमें से प्रत्येक i के वर्तमान मान को प्रिंट करता है, जो 4 है।

3

आप एक डिफ़ॉल्ट तर्क का उपयोग नहीं करना चाहते हैं - - जो कीड़े अगर गलती से एक तर्क के साथ कॉल दे सकते हैं आप एक नेस्टेड लैम्ब्डा उपयोग कर सकते हैं:

from pprint import pprint 

li = [] 

for i in range(5): 
    li.append((lambda x: lambda: pprint(x))(i)) 

for k in li: 
    k() 

यह की एक अनाम संस्करण है आपके closure फ़ंक्शन।

0

उत्तर: चूंकि लैम्ब्डा के अंदर कोड आपके वैश्विक चर i का उपयोग कर रहा है।

आपकी दूसरी संस्करण लैम्ब्डा के साथ पहली बार एक के रूप में भी ऐसा ही होगा यदि आप पैरामीटर i निकालें:

def closure(): 

के बजाय

def closure(i): 

अर्थात फ़ंक्शन के अंदर कोड वैश्विक चर i का उपयोग करेगा।

+0

के साथ डुप्लिकेट है, यह चर के दायरे से कोई लेना देना नहीं है, यह तथ्य है जो बंद है वह मूल्य के बजाय मूल्य का संदर्भ है। प्रश्न पर मेरी टिप्पणी देखें - यदि आप 'i में रेंज 'लूप को फ़ंक्शन में ले जाते हैं, तो' i' वैश्विक दायरे में मौजूद नहीं है, फिर 'k के लिए li' लूप से पहले फ़ंक्शन को कॉल करें, यह एक ही जवाब दे देंगे। – agf

+0

> यदि आप रेंज लूप में फ़ंक्शन में स्थानांतरित करते हैं, तो मैं वैश्विक दायरे में मौजूद नहीं हूं, फिर फ़ंक्शन को k लू लूप में पहले कॉल करें, यह वही उत्तर देगा ... --- यानी गैर स्थानीय? मेरा मतलब यही था। – warvariuc

+0

यह चर 'i' के लिए देख रहा है। क्योंकि कोई फ़ंक्शन तर्क नहीं है 'i' यह बाहरी दायरे से' i' लेता है। – warvariuc

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