2013-01-19 37 views
24

Beazley स्नातकोत्तर 100 का उल्लेख है:ओबीजे में बंद क्या है .__ closure__?

>>>python.__closure__ 
(<cell at 0x67f50: str object at 0x69230>,) 
>>>python.__closure__[0].cell_contents 

मैं समझता हूँ कि __closure__ एक सूची है, लेकिन यह सब सेल सामान और str वस्तु क्या है ?? यह 1-आरी ट्यूपल की तरह दिखता है?

उत्तर

29

क्लोजर सेल फ़ंक्शन द्वारा आवश्यक मानों को संदर्भित करता है लेकिन आसपास के दायरे से लिया जाता है।

जब पायथन एक नेस्टेड फ़ंक्शन को संकलित करता है, तो यह किसी भी चर को संदर्भित करता है जो संदर्भ देता है लेकिन केवल नेस्टेड फ़ंक्शन और अभिभावक स्कोप दोनों के लिए कोड ऑब्जेक्ट्स में पैरेंट फ़ंक्शन (ग्लोबल्स नहीं) में परिभाषित किया जाता है। ये co_freevars और co_cellvars क्रमशः इन कार्यों की __code__ वस्तुओं पर विशेषताओं हैं।

तब, जब आप वास्तव में (जो जब माता-पिता समारोह निष्पादित किया जाता है होता है) नेस्टेड समारोह बनाने के लिए, उन संदर्भों तो नेस्टेड कार्य करने के लिए एक बंद संलग्न करने के लिए उपयोग किया जाता है।

एक फ़ंक्शन क्लोजर में कोशिकाओं का एक ट्यूपल होता है, प्रत्येक फ्री वैरिएबल के लिए प्रत्येक एक (co_freevars में नामित); कोशिकाएं अभिभावक दायरे के स्थानीय चर के विशेष संदर्भ हैं, जो उन स्थानीय चर के मानों का पालन करती हैं। इसे एक उदाहरण से स्पष्ट है:

def foo(): 
    def bar(): 
     print(spam) 

    spam = 'ham' 
    bar() 
    spam = 'eggs' 
    bar() 
    return bar 

b = foo() 
b() 

उपरोक्त उदाहरण में, समारोह bar एक बंद सेल, जो समारोह foo में spam की ओर इशारा करता है। सेल spam के मान का पालन करता है। सबसे महत्वपूर्ण बात यह है कि, एक बार foo() पूर्ण हो जाता है और bar लौटा दिया जाता है, तो सेल foo के अंदर परिवर्तनीय spam के मान को संदर्भित करता है, भले ही सेल मानता है (स्ट्रिंग eggs)।

इस प्रकार, ऊपर कोड आउटपुट:

>>> b=foo() 
ham 
eggs 
>>> b() 
eggs 

और b.__closure__[0].cell_contents'eggs' है।

ध्यान दें कि बंद होने पर को bar() को कहा जाता है; बंद करने का मूल्य यहां कैप्चर नहीं करता है। यही कारण है कि कुछ फ़र्क पड़ता है जब आप उस संदर्भ पाश चर (lambda भाव या def बयानों के साथ) नेस्टेड कार्यों का उत्पादन:,

def foo(): 
    bar = [] 
    for spam in ('ham', 'eggs', 'salad'): 
     bar.append(lambda: spam) 
    return bar 

for bar in foo(): 
    print bar() 

ऊपर एक पंक्ति में salad तीन बार प्रिंट होगा क्योंकि तीनों lambda कार्यों का संदर्भ spam चर , जब फ़ंक्शन ऑब्जेक्ट बनाया गया था तो वह मान नहीं था। for लूप खत्म होने तक, spam'salad' पर बाध्य था, इसलिए सभी तीन बंद होने से उस मान को हल किया जाएगा।

4

यह पुराना func_closure के लिए नया पायथन 3 नाम है।

http://docs.python.org/3.0/whatsnew/3.0.html

समारोह विशेषताओं func_X नामित __X__ फार्म का उपयोग करने के लिए, उपयोगकर्ता परिभाषित विशेषताओं के लिए समारोह विशेषता नाम स्थान में इन नामों को मुक्त नाम दिया गया है। बुद्धि, func_closure, func_code, func_defaults, func_dict, func_doc, func_globals करने के लिए, func_name__closure__ को क्रमश: नाम दिया गया __code__, __defaults__, __dict__, __doc__, __globals__, __name__,।

संक्षेप में:

__closure__None है या कोशिकाओं है कि समारोह के नि: शुल्क चर के लिए बाध्यकारी होते हैं की एक tuple

इसके अलावा, यह लिखने योग्य नहीं है।

संदर्भ: http://docs.python.org/ref/types.html

उदाहरण अजगर < 3 (तो मैं उपयोग कर रहा हूँ func_closure)

def foo(): 
    x = "I am used" 
    y = "I am free" 
    z = "I am free too" 

    def bar(x): 
     return x, y, z 

    return bar 

c = foo().func_closure 

print [i.cell_contents for i in c] 

आउटपुट:

>>> 
['I am free', 'I am free too'] 

foo के रूप में समारोह bar लौटा रहा है जो उपयोग कर रहा है इसका अपना मूल्यहै, लेकिन y या z नहीं। तो, वे __closure__ के अंतर्गत आते हैं।

1
>>> def f(): 
...  a = "HELO" 
...  b = 1.0 
...  def w(c): 
...   return a,b,c 
...  return w 

>>> w = f() 
>>> w.__closure__ 
(<cell at 0xa05c4ac: str object at 0x9e91b74>, <cell at 0xa05c3bc: float object at 0xb733dde8>) 
>>> w.__closure__[0].cell_contents 
'HELO' 
>>> w.__closure__[1].cell_contents 
1.0 

मैं सेल कहीं और इस्तेमाल किया प्रकार कभी नहीं देखा है। ऐसा लगता है कि बंद करने के चर को पकड़ने के उद्देश्य से बनाया गया है।

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

  • कोई संबंधित समस्या नहीं^_^