'छोरों' के लिए पायथन में स्कोपिंग


177

मैं अजगर के डांटने के नियमों के बारे में नहीं पूछ रहा हूं; मैं आमतौर पर समझता हूं कि लूप के लिए पायथन में स्कूपिंग कैसे काम करता है। मेरा प्रश्न यह है कि इस तरह से डिजाइन निर्णय क्यों किए गए थे। उदाहरण के लिए (कोई सज़ा का इरादा नहीं):

for foo in xrange(10):
    bar = 2
print(foo, bar)

ऊपर (9,2) प्रिंट होगा।

यह मुझे अजीब लगता है: 'फू' वास्तव में सिर्फ लूप को नियंत्रित करता है, और लूप के अंदर 'बार' को परिभाषित किया गया था। मैं समझ सकता हूं कि लूप के बाहर 'बार' का पहुंचना क्यों जरूरी हो सकता है (अन्यथा, लूप के लिए बहुत सीमित कार्यक्षमता होगी)। मुझे समझ में नहीं आता है कि लूप के बाहर निकलने के बाद कंट्रोल वैरिएबल के दायरे में रहना क्यों जरूरी है। मेरे अनुभव में, यह केवल वैश्विक नामस्थान को बंद कर देता है और उन त्रुटियों को ट्रैक करना कठिन बनाता है जिन्हें अन्य भाषाओं में व्याख्याताओं द्वारा पकड़ा जाएगा।


6
यदि आप नहीं चाहते कि forलूप आपके वैश्विक नामस्थान को अव्यवस्थित करे, तो इसे किसी फ़ंक्शन में लपेटें। क्लोजर गेलरी!
२०

24
जब तक आप वैश्विक नेमस्पेस (असामान्य) में एक लूप नहीं चला रहे हैं, यह एक स्थानीय नामस्थान को अव्यवस्थित कर रहा है।
ग्लेन मेनार्ड

3
यदि यह मौजूद नहीं था, तो आप लूप के अंदर छोड़ दिए गए बिंदु पर बाद में प्रोसेसिंग कैसे जारी रखेंगे? लूप से पहले नियंत्रण चर को परिभाषित करें ?
एंडोलिथ

9
@endolith हाँ ... क्यों की आवश्यकता नहीं है?
स्टीवन लू

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

जवाबों:


107

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

अपडेट करें

यहाँ इस विषय पर एक अच्छी चर्चा है: http://mail.python.org/pipermail/python-ideas/2008-October/002109.html

लूप के लिए लूप वेरिएबल को स्थानीय बनाने के पिछले प्रस्तावों ने मौजूदा कोड की समस्या पर ठोकर खाई है जो लूप से बाहर निकलने के बाद लूप वैरिएबल पर निर्भर करता है, और ऐसा लगता है कि इसे एक वांछनीय विशेषता माना जाता है।

संक्षेप में, आप शायद इसे पायथन समुदाय पर दोष लगा सकते हैं: पी


2
यदि प्रेरण चर का दायरा लूप के शरीर तक सीमित होता तो व्याकरण अधिक जटिल कैसे होता? इस तरह का बदलाव अजगर में शब्दार्थ विश्लेषण तक ही सीमित होगा, इसके व्याकरण के लिए नहीं।
चार्ल्स

6
पाइथन में लूप्स ब्लॉक नहीं हैं। इस तरह का व्यवहार परिवर्तन व्याकरण को मौलिक रूप से बदलने या एक विशेष मामला प्रदान करने के लिए कहेंगे। एक प्रेरण चर की पूरी अवधारणा भी वर्तमान व्याकरण में व्यक्त नहीं की गई है। व्याकरण व्याख्या करने वाले के लिए अनुबंध प्रदान करता है। मेरा कहना यह है कि मैं इस बात को नहीं समझ सकता कि व्याकरण को अधिक जटिल बनाए बिना इस व्यवहार में बदलाव कैसे किया जा सकता है। डिज़ाइन निर्णय के साइड इफेक्ट के बाद से यह सब लूट है।
जेरेमी ब्राउन

1
यहाँ यह पोस्ट mail.python.org/pipermail/python-dev/2005-Seture/056677.html स्पीड और पेचीदगी के बारे में अधिक जानकारी देता है, जिसे मिस्टर ब्राउन अपनाते हैं
राजेश

62

अजगर के पास ब्लॉक नहीं हैं, जैसा कि कुछ अन्य भाषाएं (जैसे C / C ++ या Java) करती हैं। इसलिए, पायथन में स्कूपिंग यूनिट एक फ़ंक्शन है।


3
मैं असमंजस में हूँ - क्या पायथन को लूप के लिए स्कूप करने से रोकता है जिस तरह से फ़ंक्शंस किए जाते हैं?
चिमीराकोडर

36
वास्तव में सच नहीं है, यह सिर्फ इतना है कि व्याकरण ब्लॉक-पागल नहीं होता है। ( docs.python.org/reference/… ) "एक ब्लॉक पायथन प्रोग्राम टेक्स्ट का एक टुकड़ा है जिसे एक इकाई के रूप में निष्पादित किया जाता है। निम्नलिखित ब्लॉक हैं: एक मॉड्यूल, एक फ़ंक्शन बॉडी, और एक वर्ग परिभाषा ..."
जेरेमी ब्राउन

1
@ बैकहैंड, कुछ भी नहीं। इसे सिर्फ अनावश्यक समझा गया।

@ जेरेमी ब्राउन - वास्तव में। अच्छी बात है।
atzz

6
@ बैकबैक - ब्लॉक वाली भाषाओं में, लूपिंग forएक सामान्य सिद्धांत का एक प्राकृतिक विस्तार है। पायथन में इसे एक विशेष मामला होना चाहिए, और विशेष मामलों से बचा जाना चाहिए जब तक कि उन्हें सम्मोहक लाभ न हो।
atzz

39

इसका उपयोग करते समय वास्तव में उपयोगी मामला है enumerateऔर आप अंत में कुल गिनती चाहते हैं:

for count, x in enumerate(someiterator, start=1):
    dosomething(count, x)
print "I did something {0} times".format(count)

क्या यह आवश्यक है? लेकिन, यह सुनिश्चित है कि सुविधाजनक है।

एक और बात की जानकारी होना चाहिए: पायथन 2 में, सूची की समझ में परिवर्तन के रूप में अच्छी तरह से लीक कर रहे हैं:

>>> [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> x
9

लेकिन, वही पायथन 3 पर लागू नहीं होता है।


4
आप संभवतः उस elseखंड में, अर्थात कर सकते थे। else: print "I did something {0} times".format(count)- स्थानीय दायरे से पहले (जो पाइथन में मौजूद नहीं है) गायब हो जाता है
Nas Banov

3
केवल दूसरा उदाहरण पायथन 3 में काम नहीं करता है, है ना? पहला अभी भी करता है? नोट्स के रूप में क्यों इसे पायथन 3 से हटा दिया गया था?
एंडोलिथ

7
गणना के लिए, गणना में आइटम (ए, स्टार्ट = 1): # डिफॉल्ट इंडेक्स शून्य से है
ताओ झांग

3
पहला उदाहरण, एक अच्छा उपयोग मामला होने के बजाय, इस सबूत की तरह अधिक लगता है कि यह स्कूपिंग नियम खतरनाक है और इस पर भरोसा नहीं किया जाना चाहिए। क्या होगा अगर someiteratorखाली है?
अधिकतम

1
@Nas जबकि elseइस मामले में एक खंड का उपयोग किया जा सकता है, यह सामान्य रूप से काम नहीं करेगा क्योंकि लूप शरीर breakसमय से पहले हो सकता है।
jamesdlin

2

यदि आपके पास लूप में एक ब्रेक स्टेटमेंट है (और बाद में पुनरावृत्ति मूल्य का उपयोग करना चाहते हैं, तो शायद वापस लेने के लिए, किसी चीज़ को इंडेक्स करें, या स्थिति दें), यह आपको एक पंक्ति और एक असाइनमेंट बचाता है, इसलिए एक सुविधा है।


1

पायथन के लिए प्राथमिक प्रभावों में से एक एबीसी है , जो शुरुआती लोगों को प्रोग्रामिंग अवधारणाओं को पढ़ाने के लिए नीदरलैंड में विकसित एक भाषा है। पायथन के निर्माता, गुइडो वैन रोसुम ने 1980 के दशक में एबीसी पर कई वर्षों तक काम किया। मुझे पता है कि एबीसी के बारे में लगभग कुछ भी नहीं है, लेकिन जैसा कि शुरुआती के लिए इरादा है, मुझे लगता है कि इसे शुरुआती संख्या में स्कोप्स की एक सीमित संख्या होनी चाहिए, जैसे शुरुआती बेसिक।


-1

शुरुआत के लिए, यदि चर छोरों के लिए स्थानीय थे, तो उन छोरों को अधिकांश वास्तविक दुनिया प्रोग्रामिंग के लिए बेकार हो जाएगा।

वर्तमान स्थिति में:

# Sum the values 0..9
total = 0
for foo in xrange(10):
    total = total + foo
print total

पैदावार 45। अब, विचार करें कि पायथन में असाइनमेंट कैसे काम करता है। यदि लूप वेरिएबल सख्ती से स्थानीय थे:

# Sum the values 0..9?
total = 0
for foo in xrange(10):
    # Create a new integer object with value "total + foo" and bind it to a new
    # loop-local variable named "total".
    total = total + foo
print total

पैदावार 0, क्योंकि totalअसाइनमेंट के बाद लूप के अंदर लूप के totalबाहर वैसा ही वैरिएबल नहीं है । यह इष्टतम या अपेक्षित व्यवहार नहीं होगा।


5
सवाल का जवाब नहीं। ओपी फू के बारे में पूछ रहा था, कुल नहीं (या उनके उदाहरण में बार)।
जेम्स ब्रैडबरी

6
@JamesBradbury totalऔर fooअभी भी ओपी के परिदृश्य में लूप-लोकल बाइंडिंग होगा और तर्क समान है।
कर्क स्ट्रैसर

2
ओपी: "मैं समझ सकता हूं कि 'बार' के लिए लूप के बाहर पहुंचना क्यों आवश्यक हो सकता है (अन्यथा, लूप के लिए बहुत सीमित कार्यक्षमता होगी)। मुझे समझ में नहीं आता कि नियंत्रण चर के लिए बने रहना क्यों आवश्यक है लूप से बाहर निकलने के बाद गुंजाइश। " (जोर मेरा)
जेम्स ब्रैडबरी

2
@JamesBradbury आप सही हो सकते हैं, लेकिन मैंने तीन साल पहले इसका जवाब दिया था और यह अब बहस करने लायक नहीं है।
कर्क स्ट्रूसर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.