क्लोजर सेल फ़ंक्शन द्वारा आवश्यक मानों को संदर्भित करता है लेकिन आसपास के दायरे से लिया जाता है।
जब पायथन एक नेस्टेड फ़ंक्शन को संकलित करता है, तो यह किसी भी चर को संदर्भित करता है जो संदर्भ देता है लेकिन केवल नेस्टेड फ़ंक्शन और अभिभावक स्कोप दोनों के लिए कोड ऑब्जेक्ट्स में पैरेंट फ़ंक्शन (ग्लोबल्स नहीं) में परिभाषित किया जाता है। ये 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'
पर बाध्य था, इसलिए सभी तीन बंद होने से उस मान को हल किया जाएगा।