यह प्रश्न "प्रसिद्ध" और "स्पष्ट" पायथन सिंटैक्स के बहुत ही बदबूदार हिस्से को छूता है - क्या पूर्वता, लंबोदर, या सूची समझ के लिए।
मुझे नहीं लगता कि ओपी का उद्देश्य 0 से 9 तक वर्गों की एक सूची तैयार करना था। यदि ऐसा होता तो हम इसे और अधिक दे सकते थे:
squares = []
for x in range(10): squares.append(x*x)
- यह अनिवार्य वाक्यविन्यास का अच्छा ol 'तरीका है।
लेकिन बात यह नहीं है। बिंदु डब्ल्यू (हाई) टीएफ है यह अस्पष्ट अभिव्यक्ति इतनी जवाबी है? और मेरे पास अंत में आपके लिए एक मूर्खतापूर्ण मामला है, इसलिए मेरे उत्तर को बहुत जल्दी खारिज न करें (मैंने इसे नौकरी के लिए इंटरव्यू दिया था)।
इसलिए, ओपी की समझदारी ने लंबोदर की सूची लौटा दी:
[(lambda x: x*x) for x in range(10)]
यह निश्चित रूप से स्क्वेरिंग फ़ंक्शन की 10 अलग-अलग प्रतियां हैं, देखें:
>>> [lambda x: x*x for _ in range(3)]
[<function <lambda> at 0x00000000023AD438>, <function <lambda> at 0x00000000023AD4A8>, <function <lambda> at 0x00000000023AD3C8>]
मेमनों के स्मृति पतों पर ध्यान दें - वे सभी अलग हैं!
आप निश्चित रूप से इस अभिव्यक्ति का एक और "इष्टतम" (हाहा) संस्करण हो सकते हैं:
>>> [lambda x: x*x] * 3
[<function <lambda> at 0x00000000023AD2E8>, <function <lambda> at 0x00000000023AD2E8>, <function <lambda> at 0x00000000023AD2E8>]
देख? 3 बार वही लंबोदर।
कृपया ध्यान दें, कि मैंने चर के _रूप में उपयोग किया है for। यह कोई लेना देना नहीं है xमें lambda(यह lexically भारी पड़ जाता है!)। उसे ले लो?
मैं चर्चा छोड़ रहा हूं, वाक्यविन्यास पूर्वता ऐसा क्यों नहीं है, इसका मतलब यह है कि:
[lambda x: (x*x for x in range(10))]
जो हो सकता है: [[0, 1, 4, ..., 81]]या [(0, 1, 4, ..., 81)], या जो मुझे सबसे तार्किक लगता है , यह list1 तत्व का होगा - generatorमूल्यों को लौटाने वाला। यह सिर्फ मामला नहीं है, भाषा इस तरह से काम नहीं करती है।
लेकिन क्या, अगर ...
क्या होगा यदि आप forचर का निरीक्षण नहीं करते हैं , और इसे अपने lambdas में उपयोग करते हैं ???
ठीक है, फिर बकवास होता है। इसे देखो:
[lambda x: x * i for i in range(4)]
बेशक इसका मतलब है:
[(lambda x: x * i) for i in range(4)]
लेकिन इसका मतलब यह नहीं है:
[(lambda x: x * 0), (lambda x: x * 1), ... (lambda x: x * 3)]
यह सिर्फ पागल है!
सूची की समझ के लंबोदर इस समझ के दायरे के करीब हैं। एक शाब्दिक बंद, इसलिए वे संदर्भ के iमाध्यम से संदर्भित करते हैं, और जब उनका मूल्यांकन किया गया था, तो इसका मूल्य नहीं!
तो, यह अभिव्यक्ति:
[(lambda x: x * i) for i in range(4)]
लगभग बराबर है:
[(lambda x: x * 3), (lambda x: x * 3), ... (lambda x: x * 3)]
मुझे यकीन है कि हम एक अजगर डिकम्पॉइलर (जिसके द्वारा मेरा मतलब है जैसे disमॉड्यूल) का उपयोग करके अधिक देख सकते हैं , लेकिन पायथन-वीएम-अज्ञेय चर्चा के लिए यह पर्याप्त है। नौकरी के लिए इंटरव्यू के लिए बहुत कुछ।
अब, listमल्टीपलियर लैम्ब्डा कैसे बनाएं , जो वास्तव में लगातार पूर्णांक से गुणा करें? ठीक है, स्वीकृत उत्तर के समान, हमें सीधे टाई को iदूसरे में लपेटकर तोड़ने की जरूरत है lambda, जिसे सूची समझ अभिव्यक्ति के अंदर कहा जा रहा है :
इससे पहले:
>>> a = [(lambda x: x * i) for i in (1, 2)]
>>> a[1](1)
2
>>> a[0](1)
2
उपरांत:
>>> a = [(lambda y: (lambda x: y * x))(i) for i in (1, 2)]
>>> a[1](1)
2
>>> a[0](1)
1
(मेरे पास बाहरी लैम्ब्डा चर भी था = i, लेकिन मैंने तय किया कि यह स्पष्ट समाधान है - मैंने पेश किया yताकि हम सभी देख सकें कि कौन सा चुड़ैल है)।
2019-08-30 संपादित करें:
@Josoler द्वारा एक सुझाव के बाद, जो @sheridp द्वारा उत्तर में भी मौजूद है - सूची समझ "लूप वेरिएबल" का मान किसी ऑब्जेक्ट के अंदर "एम्बेडेड" किया जा सकता है - कुंजी इसके लिए सही समय पर एक्सेस करना है। ऊपर "बाद" अनुभाग इसे दूसरे में लपेटकर lambdaऔर वर्तमान मूल्य के साथ तुरंत कॉल करता है i। एक और तरीका (पढ़ने में थोड़ा आसान है - यह कोई 'वाट' प्रभाव पैदा नहीं करता है) iकिसी partialवस्तु के मूल्य को संग्रहीत करना है , और "आंतरिक" (मूल) lambdaको एक तर्क के रूप में लेना है ( partialवस्तु द्वारा आपूर्ति की गई पास) कॉल का समय), अर्थात:
2 के बाद:
>>> from functools import partial
>>> a = [partial(lambda y, x: y * x, i) for i in (1, 2)]
>>> a[0](2), a[1](2)
(2, 4)
महान, लेकिन आपके लिए अभी भी थोड़ा मोड़ है! मान लें कि हम कोड रीडर पर इसे आसान नहीं बनाना चाहते हैं, और नाम से कारक को पास करें (एक कीवर्ड तर्क के रूप में partial)। आइए कुछ नाम बदलें:
2.5 के बाद:
>>> a = [partial(lambda coef, x: coef * x, coef=i) for i in (1, 2)]
>>> a[0](1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <lambda>() got multiple values for argument 'coef'
WAT?
>>> a[0]()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <lambda>() missing 1 required positional argument: 'x'
रुको ... हम 1 से तर्क की संख्या बदल रहे हैं, और "बहुत से" से "बहुत कम" तक जा रहे हैं?
ठीक है, यह एक वास्तविक वॉट नहीं है, जब हम इस तरह coefसे गुजरते हैं partial, तो यह एक कीवर्ड तर्क बन जाता है, इसलिए इसे स्थितिगत तर्क के बाद आना चाहिए x, जैसे:
3 के बाद:
>>> a = [partial(lambda x, coef: coef * x, coef=i) for i in (1, 2)]
>>> a[0](2), a[1](2)
(2, 4)
मैं नेस्टेड लैम्ब्डा के अंतिम संस्करण को पसंद करूंगा, लेकिन प्रत्येक को अपने ...
[lambda x: x*x for x in range(10)]पहले वाले की तुलना में तेज है, क्योंकि यह बार-बार बाहरी लूप फ़ंक्शन को कॉल नहीं करता है।