2014-10-22 5 views
8

सूची comprehensions उनके कोड समारोह जहां वे इस्तेमाल कर रहे हैं में सीधे रखा है, इस तरह:पाइथन 2 में जनरेटर अभिव्यक्तियों और निर्देश/सेट समझें सूची समझ के विपरीत एक नेस्टेड फ़ंक्शन का उपयोग क्यों करती हैं?

>>> dis.dis((lambda: [a for b in c])) 
    1   0 BUILD_LIST    0 
       3 LOAD_GLOBAL    0 (c) 
       6 GET_ITER    
     >> 7 FOR_ITER    12 (to 22) 
      10 STORE_FAST    0 (b) 
      13 LOAD_GLOBAL    1 (a) 
      16 LIST_APPEND    2 
      19 JUMP_ABSOLUTE   7 
     >> 22 RETURN_VALUE   

जनरेटर भाव और dict/सेट comprehensions जबकि ज्यादातर एक अलग नेस्टेड समारोह में रखा जाता है, इस तरह:

>>> dis.dis((lambda: {a for b in c})) 
    1   0 LOAD_CONST    1 (<code object <setcomp> at 0x7ff41a3d59b0, file "<stdin>", line 1>) 
       3 MAKE_FUNCTION   0 
       6 LOAD_GLOBAL    0 (c) 
       9 GET_ITER    
      10 CALL_FUNCTION   1 
      13 RETURN_VALUE   

>>> dis.dis((lambda: {a for b in c}).func_code.co_consts[1]) 
    1   0 BUILD_SET    0 
       3 LOAD_FAST    0 (.0) 
     >> 6 FOR_ITER    12 (to 21) 
       9 STORE_FAST    1 (b) 
      12 LOAD_GLOBAL    0 (a) 
      15 SET_ADD     2 
      18 JUMP_ABSOLUTE   6 
     >> 21 RETURN_VALUE   

पायथन 3 में, इन सभी को नेस्टेड फ़ंक्शन में रखा गया है।

कोड एक अलग नेस्टेड फ़ंक्शन में क्यों रखा गया है? मुझे बहुत समय पहले आसपास के दायरे में फैलाने वाली समझ और/या जीनेक्सप्रैर चर को ठीक करने के इच्छुक लोगों के बारे में कुछ पढ़ना याद रखना, क्या यह उस चीज़ के लिए ठीक था?

पाइथन 2 में शेष सूची से सूची समझ अलग-अलग क्यों लागू की जाती हैं? पिछली संगतता के कारण? (I सोचा मैंने जनरेटर अभिव्यक्तियों के परिचय के बाद बहुत सारे स्पिलिंग फिक्सिंग के बारे में बात सुनी, हालांकि, लेकिन शायद मैं वास्तव में पुरानी चर्चाओं या कुछ पढ़ रहा हूं)

उत्तर

10

हाँ, आप सही हैं। पायथन 3.x में, यह परिवर्तनीय रिसाव को ठीक करने के लिए पेश किया गया है। , History of Python blog के पद, माना जाता है BDFL खुद द्वारा लिखित से हवाला देते हुए

हम भी सूची comprehensions और जनरेटर भाव के बीच तुल्यता सुधार करने के लिए अजगर 3 में एक और परिवर्तन किया,। अजगर 2 में, सूची समझ "लीक" आसपास के दायरे में लूप नियंत्रण चर:

x = 'before' 
a = [x for x in 1, 2, 3] 
print x # this prints '3', not 'before' 

इस सूची comprehensions के मूल कार्यान्वयन के एक विरूपण साक्ष्य था, यह वर्षों से पाइथन के "गंदे छोटे रहस्य" में से एक था। यह सूची समझने के लिए एक जानबूझकर समझौता के रूप में शुरू हुआ, और जब शुरुआती लोगों के लिए यह आम बात नहीं थी, तो यह निश्चित रूप से लोगों को कभी-कभी ठोकर खाती थी। जनरेटर अभिव्यक्तियों के लिए हम ऐसा नहीं कर सके। जनरेटर एक्सप्रेशन जेनरेटर का उपयोग करके लागू किए जाते हैं, जिनके निष्पादन के लिए एक अलग निष्पादन फ्रेम की आवश्यकता होती है। इस प्रकार, जेनरेटर एक्सप्रेशन (विशेष रूप से यदि वे एक लघु अनुक्रम पर पुनरावृत्त होते हैं) सूची समझ से कम कुशल थे।

हालांकि, पायथन 3 में, हमने जनरेटर अभिव्यक्ति के लिए समान कार्यान्वयन रणनीति का उपयोग करके सूची समझों के "गंदे छोटे रहस्य" को ठीक करने का निर्णय लिया। इस प्रकार, पायथन 3 में, उपरोक्त उदाहरण (print(x) का उपयोग करने के लिए संशोधन के बाद :-) 'पहले' प्रिंट करेगा, यह साबित करेगा कि सूची समझ में 'x' अस्थायी रूप से छाया करता है लेकिन आसपास के दायरे में 'x' को ओवरराइड नहीं करता है।

आपके सभी प्रश्नों को हाइलाइट किए गए टेक्स्ट द्वारा उत्तर दिया जाता है।

+2

यहां [एक लिंक] (https://mail.python.org/pipermail/python-3000/2007-March/006017.html) थ्रेड पर है जहां निक कोग्लान और जॉर्ज ब्रैंडल ने उन्हें इस तरह कार्यान्वित करने के लिए तर्क पर चर्चा की – Felipe

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