2010-12-13 26 views
5

में कार्यों की सूची तैयार मैं निम्नलिखित अजगर कोड है कि अनाम प्रक्रियाएं की एक सूची बनाता है:अजगर

basis = [ (lambda x: n*x) for n in [0, 1, 2] ]  
print basis[0](1) 

मैं इसे

basis = [ (lambda x: 0*x), (lambda x: 1*x), (lambda x: 2*x) ] 
print basis[0](1) 

के बराबर होने का हालांकि, इसकी अपेक्षा की होगी जबकि दूसरा स्निपेट 0 प्रिंट करता है जो मैं अपेक्षा करता हूं, पहला प्रिंट 2. कोड के पहले स्निपेट में क्या गड़बड़ है, और यह अपेक्षित व्यवहार क्यों नहीं करता है?

+0

संबंधित सवाल: http://stackoverflow.com/q/139819/4279 – jfs

उत्तर

8

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

>>> basis = [ (lambda x,n=n: n*x) for n in [0, 1, 2] ]  
>>> print basis[0](1) 
0 
+3

इस तकनीक को अक्सर कॉलबैक फ़ंक्शंस के रूप में विधियों को पारित करने के लिए उपयोग किया जाता है। ऐसा लगता है कि 'register_event_handler (event = evt, callback = lambda cbVar1, cbVar2, s = self: s.handle_evt (cbVar1, cbVar2))। –

2

समस्या यह है कि पहले उदाहरण में, प्रत्येक लैम्ब्डा एक ही n से जुड़ा हुआ है - दूसरे शब्दों में, यह वैरिएबल के मूल्य को नहीं, चर को कैप्चर कर रहा है। चूंकि n में लूप के अंत में 2 का मान है, प्रत्येक लैम्ब्डा n के लिए मान 2 का उपयोग कर रहा है। हर बार लूप के माध्यम से आप एक नया देने के लिए

basis = [ (lambda x,n=n: n*x) for n in [0, 1, 2] ] 
print basis[0](1) 

क्योंकि डिफ़ॉल्ट पैरामीटर मान स्थिरांक हैं, n=n के दाईं ओर n मूल्यांकन किया जाएगा:

जाहिर है आप डिफ़ॉल्ट पैरामीटर इस समस्या को हल करने के लिए उपयोग कर सकते हैं कब्जा मूल्य

+0

इसे ठीक करने के तरीके पर कोई सुझाव? – dzhelil

+1

सेइल: मैंने अपना उत्तर एक सुझाए गए फ़िक्स की पेशकश करने के लिए संपादित किया है, लेकिन यह बहुत ही सुरुचिपूर्ण नहीं है। – Gabe

+0

डिफ़ॉल्ट पैरामीटर सुरुचिपूर्ण नहीं हो सकते हैं, लेकिन वे स्पष्ट आंशिक मूल्यांकन की तुलना में देखने के लिए बहुत आसान हैं जैसे कि मैं करता था: 'base = [(lambda n: (lambda x: n * x)) (n) एन में सीमा के लिए (3)] '। :/डिफ़ॉल्ट पैरामीटर अपरिवर्तनीय होने की भावना में "निरंतर" नहीं है, लेकिन इसका मूल्यांकन लैम्ब्डा के '.func_defaults' में किया जाता है और बाध्य होता है। क्लोजर पैरामीटर भी करते हैं, लेकिन स्पष्ट रूप से एक और जादुई तरीके से ... –

3

क्योंकि यह "नाम से गुजरता है"।

यही है, जब lambda चलाया जाता है, यह n*x कार्यान्वित: x (यह एक पैरामीटर है) 1 के लिए बाध्य है, n माहौल में देखा जाता है (यह अब 2 है)। तो, परिणाम 2.

+0

यह स्पष्ट नहीं करता है कि जब हम जनरेटर समझ का उपयोग करते हैं, तो वही व्यवहार क्यों प्रदर्शित होता है, जो 'स्थानीय" ('' 'में' रिसाव ''n' नहीं होता है। AFAICT, 'n' का मान लैम्ब्डा के '.func_closure' से देखा जाता है, और यह बिल्कुल स्पष्ट नहीं है कि यह जादूई रूप से जो भी' n' अंतिम रूप से संदर्भित होता है, जब' n' मौजूद नहीं होता है। –

0

मैं 7 में कार्ल Knechtel (दिसम्बर 13 '10 से टिप्पणी की समझ के साथ मदद करना चाहते हैं : 32)। निम्नलिखित कोड दिखाता है कि जनरेटर का उपयोग, मूल लैम्ब्डा परिभाषा इच्छित परिणाम देता है, लेकिन यह सूची या टपल का उपयोग कर नहीं करता है:

>>> #GENERATOR 
... basis = ((lambda x: n*x) for n in [0, 1, 2]) 
>>> print(type(basis)) 
<type 'generator'> 
>>> basis = ((lambda x: n*x) for n in [0, 1, 2]) 
>>> print([x(3) for x in basis]) 
[0, 3, 6] 
>>> #TUPLE 
... basis = tuple((lambda x: n*x) for n in [0, 1, 2]) 
>>> print(type(basis)) 
<type 'tuple'> 
>>> print([x(3) for x in basis]) 
[6, 6, 6] 
>>> #LIST 
... basis = list((lambda x: n*x) for n in [0, 1, 2]) 
>>> print(type(basis)) 
<type 'list'> 
>>> print([x(3) for x in basis]) 
[6, 6, 6] 
>>> #CORRECTED LIST 
... basis = list((lambda x, n=n: n*x) for n in [0, 1, 2]) 
>>> print(type(basis)) 
<type 'list'> 
>>> print([x(3) for x in basis]) 
[0, 3, 6]