2012-06-19 6 views
13

में अजीब बंद व्यवहार मैं एक निम्नलिखित सरल कोड है। लेकिन यह आंतरिक रूप से कैसे काम करता है?अजगर

AFAIK, पायथन चर वस्तुएं केवल संदर्भों के संदर्भ में हैं, इसलिए पहले बंद करने से ऑब्जेक्ट को पहले i संदर्भ संलग्न करना होगा - और यह ऑब्जेक्ट निश्चित रूप से 1, 3 ओ_ओ नहीं है। यह कैसे होता है कि पाइथन क्लोजर इस चर संदर्भ के ऑब्जेक्ट के बजाय चर स्वयं संलग्न करता है? क्या यह परिवर्तनीय नाम को सादा पाठ के रूप में सहेजता है, कुछ "परिवर्तनीय संदर्भ" या क्या?

उत्तर

9

क्लोजर चर का संदर्भ नहीं देते हैं, बल्कि स्कॉप्स पर। चूंकि इसके दायरे में i का अंतिम मान '3' है, इसलिए सभी तीन बंद होने पर वही वापसी होती है। "ताला" करने के लिए एक चर के वर्तमान मूल्य, बस इसके लिए एक नया गुंजाइश बनाने के लिए: @ thg435 बताते

def get() : return [ (lambda x: lambda: x)(i) for i in [ 1, 2, 3 ] ] 
for f in get() : print(f()) 
+0

यह कुछ अतिरिक्त जानकारी तो मैं देख सकते हैं कि छिपा चर "सेव" करने के लिए गुंजाइश है, यह का उपयोग, आदि उपयोग किया जाता है इस विषय पर उपलब्ध है? – grigoryvp

+2

'(लैम्ब्डा एक्स: लैम्ब्डा: एक्स) (i) 'पाइथन में मैंने देखा है सबसे उग्र चीजों में से एक है। Ick। (यह नहीं कि आपका जवाब गलत है या बुरा है, प्रति-से, बस कह रहा है - इसे पढ़ना मुश्किल है)। –

+2

@EyeofHell: मुझे लगता है [स्फूर्ति-227] (http://www.python.org/dev/peps/pep-0227/) अजगर scoping नियमों के बारे में विहित दस्तावेज है। इसके अलावा, यहां SO पर कुछ अच्छे उत्तर दिए गए हैं, उदा। [यहां] (http://stackoverflow.com/questions/291978/short-description-of-python-scoping-rules) – georg

11

के रूप में, एक लैम्ब्डा उस पल में मूल्यों को संपुटित नहीं होंगे, बल्कि गुंजाइश। वहाँ बहुत छोटा तरीकों से आप यह पता कर सकते हैं कर रहे हैं:

लैम्ब्डा डिफ़ॉल्ट तर्क

[ lambda v=i: v for i in [ 1, 2, 3 ] ] 

"हैक" या का उपयोग functools.partial

from functools import partial 
[ partial(lambda v: v, i) for i in [ 1, 2, 3 ] ] 

अनिवार्य रूप से आप के लिए स्थानीय होने की गुंजाइश बढ़ना है जो काम आप बना रहे हैं। आम तौर पर मुझे partial का उपयोग करना पसंद है क्योंकि आप इसे एक कॉल करने योग्य, और किसी भी तर्क और कार को उचित बंद करने के साथ कॉल करने योग्य बना सकते हैं। आंतरिक रूप से, यह आपके मूल कॉल करने योग्य है ताकि आपके लिए दायरा स्थानांतरित हो।

+5

+1 आंशिक उपयोग करने के लिए, मुझे लगता है कि यह एक बहुत साफ दृष्टिकोण है। हो सकता है कि आप अपना कोड संपादित करना चाहें, पीईपी -8 के अनुसार सूची ब्रैकेट के अंदर रिक्त स्थान खराब हैं। (मुझे पता है कि आप पूछताछ का पालन कर रहे थे, मैंने इसे संपादित किया)। –

+0

@ लैटवेयर: धन्यवाद! lambdas शांत हैं, लेकिन मैं हमेशा उन्हें पढ़ने के लिए और अधिक गन्दा पाते हैं। आंशिक बस इतना अधिक पठनीय और पोर्टेबल लगता है। – jdi

+0

100% सहमत हैं, मैं जहां भी कर सकता हूं भेड़ के बच्चे से बचने की कोशिश करता हूं, और यह एक प्रमुख मामला है जहां आंशिक दोनों स्पष्ट और सरल दोनों हैं। –

4

प्रत्येक lambda वास्तव में उसी i का जिक्र कर रहा है, जो सूची समझ द्वारा बनाई गई एक चर है। सूची समझ की समाप्ति पर, i (जो एक समारोह के भीतर यह encapsulating और लौटने यह, अर्थात् lambda द्वारा रोका जाता है) अंतिम तत्व का मान है कि यह जब तक यह क्षेत्र से बाहर चला जाता है को सौंपा गया था बनाए रखता है। जैसा कि अन्य ने इंगित किया है, बंद करने से मूल्यों की प्रतियां नहीं रहती हैं, बल्कि वे अपने दायरे में परिभाषित चरों के संदर्भ बनाए रखती हैं।