दिलचस्प पोस्ट
इसका अर्थ क्या है? {"<user xmlns = ''> उम्मीद नहीं की गई थी।) ट्विटर एक्सपेराइलिंग करना सीएसवी फ़ाइल आयात। नेट में अपने आप को एक वेक्टर संलग्न करने का अच्छा तरीका टीसीपी सॉकेट वियोग का पता लगाने के लिए (सी बर्कले सॉकेट के साथ) लॉलीपॉप में ऐप मैच करने के लिए स्टेटस बार का रंग कैसे बदल सकता है? तिथि सीमा के आधार पर लॉग फ़ाइल प्रविष्टियां फ़िल्टर करें क्यों RelayCommand अन्य डेवलपर्स के लिए एक ढांचा या लायब्रेरी कैसे तैयार करें, सुरक्षित तरीके से? वीबीए में उप-डीडी की सूची प्राप्त करें सत्यापन के साथ OAuth .NET मैं कैसे tastypie का उपयोग कर django में प्रवेश कर सकते हैं एक अंक के अंकों को जोड़ – अजगर "जोर" कीवर्ड क्या करता है? जेनेरिक सूची के सरणी

पायथन क्लोज़र्स पढ़ें / लिखें

क्लोज़र एक अविश्वसनीय रूप से उपयोगी भाषा सुविधा है। वे हमें चतुर चीजें करते हैं जो अन्यथा बहुत सारे कोड लेते हैं, और अक्सर हमें उस कोड को लिखने में सक्षम करते हैं जो कि अधिक सुरुचिपूर्ण और अधिक स्पष्ट है। पायथन 2.x में, क्लोजर वैरिएबल नाम रिबूट नहीं हो सकते हैं; वह है, एक अन्य व्याख्यात्मक गुंजाइश में परिभाषित एक फ़ंक्शन some_var = 'changed!' तरह कुछ नहीं कर सकता some_var = 'changed!' इसके स्थानीय दायरे के बाहर चर के लिए क्या कोई यह समझा सकता है कि ऐसा क्यों है? ऐसी परिस्थितियों में मैं एक बंद करना चाहता हूं जो बाहरी दायरे में चर को पुन: rebind करता है, लेकिन यह संभव नहीं था। मुझे पता है कि लगभग सभी मामलों में (यदि नहीं, तो सभी), यह व्यवहार कक्षाओं के साथ प्राप्त किया जा सकता है, लेकिन यह अक्सर साफ या सुरुचिपूर्ण नहीं होता है मैं इसे बंद करने के साथ क्यों नहीं कर सकता?

यहां रीबिंंग बंद करने का एक उदाहरण है:

 def counter(): count = 0 def c(): count += 1 return count return c 

जब आप इसे कॉल करते हैं तो यह वर्तमान व्यवहार है:

 >>> c() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in c UnboundLocalError: local variable 'count' referenced before assignment 

इसके बजाय मैं इसे करना चाहता हूं:

 >>> c() 1 >>> c() 2 >>> c() 3 

वेब के समाधान से एकत्रित समाधान "पायथन क्लोज़र्स पढ़ें / लिखें"

इग्नेसियो के जवाब पर विस्तार करने के लिए:

 def counter(): count = 0 def c(): nonlocal count count += 1 return count return c x = counter() print([x(),x(),x()]) 

पायथन 3 में [1,2,3] देता है; counter() आमंत्रण counter() स्वतंत्र काउंटर प्रदान करते हैं अन्य समाधान – विशेष रूप से itertools / yield का उपयोग itertools अधिक मुहावरेदार है

आप ऐसा कर सकते हैं और यह अधिक या कम तरह से काम करेगा:

 class counter(object): def __init__(self, count=0): self.count = count def __call__(self): self.count += 1 return self.count 

या, एक हैक का एक सा:

 def counter(): count = [0] def incr(n): n[0] += 1 return n[0] return lambda: incr(count) 

मैं पहले समाधान के साथ जाना था

संपादित करें: टेक्स्ट के बड़े ब्लॉग को पढ़ने के लिए मुझे यही मिलता है

वैसे भी, कारण पायथन बंद करने की जगह सीमित है "क्योंकि Guido ऐसा महसूस किया।" पायथन की शुरूआत 90 के दशक में, ओ ओ के उत्थान में की गई थी। लोग जो चाहें भाषा की सूची की सूची में क्लोजर कम थे जैसे कि प्रथम श्रेणी के कार्यों, बंद होने और अन्य चीजों की तरह कार्यात्मक विचार मुख्यधारा की लोकप्रियता में अपना रास्ता बनाते हैं, जैसे कि पायथन के लिए भाषाएं उन पर काबू पाती हैं, इसलिए उनका उपयोग थोड़ा अजीब हो सकता है, क्योंकि यह ऐसा नहीं है कि भाषा को किस प्रकार डिजाइन किया गया था।

<rant on="Python scoping">

इसके अलावा, पायथन (2.x) ने अन्य चीजों के बीच, बंद करने के एक समझदार कार्यान्वयन के साथ हस्तक्षेप करने के बारे में विचारों में (मेरी राय में) अजीब विचार किया है। यह हमेशा मुझे परेशान करता है कि यह:

 new = [x for x in old] 

हमारे द्वारा उपयोग किए गए दायरे में परिभाषित नाम x हमें छोड़ देता है, क्योंकि यह (मेरी राय में) एक अवधारणात्मक रूप से छोटा क्षेत्र है (यद्यपि पायथन को स्थिरता के लिए अंक मिलते हैं, क्योंकि लूप के साथ समान कार्य करना एक ही व्यवहार है। इस से बचने का एकमात्र तरीका map का उपयोग करना है।)

वैसे भी, </rant>

3.x में nonlocal इस उपाय चाहिए।

मैं एक जनरेटर का उपयोग करेगा:

 >>> def counter(): count = 0 while True: count += 1 yield(count) >>> c = counter() >>> c.next() 1 >>> c.next() 2 >>> c.next() 3 

संपादित करें : मेरा मानना ​​है कि आपके प्रश्न का अंतिम उत्तर पीईपी -3104 है :

नेस्टेड स्कॉप्स का समर्थन करने वाली अधिकांश भाषाओं में, कोड निकटतम संलग्न क्षेत्र में किसी भी नाम का उल्लेख कर सकता है या रिबंड कर सकता है (असाइन कर सकता है) वर्तमान में, पायथन कोड किसी भी संलग्न क्षेत्र में एक नाम का उल्लेख कर सकता है, लेकिन यह केवल दो स्कोप में नामों को पुन: वितरित कर सकता है: स्थानीय क्षेत्र (साधारण असाइनमेंट) या मॉड्यूल-वैश्विक दायरे (वैश्विक घोषणा का उपयोग करके)।

यह सीमा कई बार पायथन-देव मेलिंग सूची और अन्य जगहों पर उठायी गयी है, और इस सीमा को दूर करने के तरीकों के लिए विस्तारित चर्चा और कई प्रस्तावों का नेतृत्व किया है। यह पीईपी विभिन्न विकल्पों का सारांश देता है जिन्हें सुझाव दिया गया है, प्रत्येक के लिए उल्लेख किए गए फायदे और नुकसान के साथ।

संस्करण 2.1 से पहले, स्कॉप्स के पायथन का इलाज मानक सी की तरह था: एक फ़ाइल के भीतर वैश्विक और स्थानीय क्षेत्र का केवल दो स्तर थे। सी में, यह इस तथ्य का एक स्वाभाविक परिणाम है कि फ़ंक्शन परिभाषाएं नेस्टेड नहीं की जा सकतीं। लेकिन पायथन में, हालांकि फ़ंक्शन आमतौर पर शीर्ष स्तर पर परिभाषित होते हैं, फ़ंक्शन परिभाषा को कहीं भी लागू किया जा सकता है। इसने पायथन को शब्दार्थियों के बिना नेस्टेड स्कॉपिंग का वाक्यविन्यास रूप दिया, और कुछ प्रोग्रामरों को आश्चर्यचकित करने वाली विसंगतियां उत्पन्न हुईं – उदाहरण के लिए, एक पुनरावर्ती समारोह जो शीर्ष स्तर पर काम किया जाता था, जब किसी अन्य फ़ंक्शन के अंदर ले जाया जाता है, क्योंकि रिकर्सिव फ़ंक्शन के अपने नाम अब अपने शरीर के दायरे में दिखाई नहीं देगा यह अंतर्ज्ञान का उल्लंघन करता है कि विभिन्न संदर्भों में रखा जाने पर फ़ंक्शन को लगातार व्यवहार करना चाहिए।

कार्यों में गुण भी हो सकते हैं, इसलिए ये भी काम करेगा:

 def counter(): def c(): while True: yield c.count c.count += 1 c.count = 0 return c 

हालांकि, इस विशिष्ट उदाहरण में, मैं जेबोची द्वारा सुझाए गए एक जनरेटर का उपयोग करूँगा

क्यों , मैं निश्चित रूप से नहीं कह सकता, लेकिन मुझे लगता है कि यह एक स्पष्ट डिजाइन पसंद नहीं है, बल्कि अजगर के कभी-कभी अजीब तरह के नियमों (और विशेष रूप से अपने scoping नियमों का कुछ हद तक विकास) का एक अवशेष है।

यह व्यवहार आधिकारिक पायथन ट्यूटोरियल के साथ-साथ पायथन निष्पादन मॉडल में अच्छी तरह समझाया गया है। विशेष रूप से, ट्यूटोरियल से:

पायथन का एक विशेष प्रकार का मुकाबला यह है कि – यदि कोई वैश्विक वक्तव्य प्रभाव में नहीं है – नाम के असाइनमेंट हमेशा आंतरिक गुंजाइश में जाते हैं।

हालांकि, यह इस बारे में कुछ नहीं कहता कि वह इस तरह से क्यों व्यवहार करता है।

कुछ और जानकारी PEP 3104 से आती है, जो कि इस स्थिति को पायथन 3.0 के लिए सामना करने का प्रयास करता है।
वहां, आप देख सकते हैं कि यह इस तरह से है क्योंकि निश्चित समय पर, क्लासिक स्थिर नेस्टेड स्कॉप्स को पेश करने के बजाए इसे सबसे अच्छा समाधान माना जाता था (देखें पुन: स्क्रॉपिंग (फिर से: लम्बाडा बाइंडिंग हल?) )

उस ने कहा, मेरी खुद की व्याख्या भी है।
पायथन नामस्थान के रूप में शब्दकोशों को लागू करता है; जब एक चर के लिए एक लुकअप आंतरिक में विफल रहता है, तो यह बाहरी और इतने पर की कोशिश करता है, जब तक यह बिल्टिन तक पहुंचता नहीं है।
हालांकि, एक परिवर्तनीय बाध्यकारी एक पूरी तरह से अलग चीज है, क्योंकि आपको किसी विशिष्ट नेमस्पेस को निर्दिष्ट करना होगा – यह हमेशा सबसे कम है (जब तक कि आप "वैश्विक" ध्वज सेट नहीं करते हैं, इसका मतलब यह हमेशा वैश्विक नाम स्थान है)।
आखिरकार, अलग-अलग एल्गोरिदम को देखने और बाध्य करने के चर के लिए उपयोग किया जाता है, बंद होने के कारण केवल पढ़ने के लिए पायथन में होता है
लेकिन, फिर से, यह सिर्फ मेरी अटकलें हैं 🙂

ऐसा नहीं है कि वे केवल पढ़ने के लिए होते हैं, जितना कि गुंजाइश अधिक सख्त है जिसे आप समझते हैं। यदि आप पायथन 3+ में nonlocal नहीं कर सकते हैं, तो आप कम से कम स्पष्ट स्कोपिंग का उपयोग कर सकते हैं। पायथन 2.6.1, मॉड्यूल स्तर पर स्पष्ट स्कॉपींग के साथ:

 >>> def counter(): ... sys.modules[__name__].count = 0 ... def c(): ... sys.modules[__name__].count += 1 ... return sys.modules[__name__].count ... sys.modules[__name__].c = c ... >>> counter() >>> c() 1 >>> c() 2 >>> c() 3 

छद्म-वैश्विक मॉड्यूल वेरिएबल (अभी भी पायथन 2.6.1) का उपयोग करने के बजाय, गिनती चर के लिए अधिक सीमित दायरे के लिए थोड़ा अधिक काम की आवश्यकता है:

 >>> def counter(): ... class c(): ... def __init__(self): ... self.count = 0 ... cinstance = c() ... def iter(): ... cinstance.count += 1 ... return cinstance.count ... return iter ... >>> c = counter() >>> c() 1 >>> c() 2 >>> c() 3 >>> d = counter() >>> d() 1 >>> c() 4 >>> d() 2