Python Language
चर स्कोप और बाइंडिंग
खोज…
वाक्य - विन्यास
- वैश्विक ए, बी, सी
- nonlocal a, b
- x = कुछ # x बांधता है
- (x, y) = कुछ # x और y को बांधता है
- x + = कुछ # x बांधता है। इसी तरह अन्य सभी "op =" के लिए
- डेल एक्स # बाइंड्स एक्स
- किसी चीज़ में x के लिए: # x को बांधता है
- x के साथ कुछ के साथ: # x को बांधता है
- अपवाद को छोड़कर पूर्व के रूप में: # ब्लॉक के अंदर पूर्व बांधता है
सार्वत्रिक चर
पायथन में, फ़ंक्शन के अंदर चर को स्थानीय माना जाता है अगर और केवल अगर वे एक असाइनमेंट स्टेटमेंट के बाईं ओर दिखाई देते हैं, या कुछ अन्य बाध्यकारी घटना; अन्यथा इस तरह के बंधन को वैश्विक दायरे तक संलग्न कार्यों में देखा जाता है। यह सच है भले ही असाइनमेंट स्टेटमेंट कभी निष्पादित न हो।
x = 'Hi'
def read_x():
print(x) # x is just referenced, therefore assumed global
read_x() # prints Hi
def read_y():
print(y) # here y is just referenced, therefore assumed global
read_y() # NameError: global name 'y' is not defined
def read_y():
y = 'Hey' # y appears in an assignment, therefore it's local
print(y) # will find the local y
read_y() # prints Hey
def read_x_local_fail():
if False:
x = 'Hey' # x appears in an assignment, therefore it's local
print(x) # will look for the _local_ z, which is not assigned, and will not be found
read_x_local_fail() # UnboundLocalError: local variable 'x' referenced before assignment
आम तौर पर, एक कार्यक्षेत्र के अंदर एक असाइनमेंट समान नाम के किसी भी बाहरी चर को छाया देगा:
x = 'Hi'
def change_local_x():
x = 'Bye'
print(x)
change_local_x() # prints Bye
print(x) # prints Hi
एक नाम global
घोषित करने का मतलब है कि, बाकी गुंजाइश के लिए, नाम के लिए कोई भी असाइनमेंट मॉड्यूल के शीर्ष स्तर पर होगा:
x = 'Hi'
def change_global_x():
global x
x = 'Bye'
print(x)
change_global_x() # prints Bye
print(x) # prints Bye
global
कीवर्ड का अर्थ है कि असाइनमेंट मॉड्यूल के शीर्ष स्तर पर होगा, कार्यक्रम के शीर्ष स्तर पर नहीं। अन्य मॉड्यूल को अभी भी मॉड्यूल के भीतर चर की सामान्य डॉटेड पहुंच की आवश्यकता होगी।
सारांशित करने के लिए: यह जानने के लिए कि क्या चर x
किसी फ़ंक्शन के लिए स्थानीय है, आपको पूरे फ़ंक्शन को पढ़ना चाहिए:
- यदि आपने
global x
पाया है, तोx
एक वैश्विक चर है - यदि आपने
nonlocal x
पाया है, तोx
एक एनक्लोजिंग फ़ंक्शन के अंतर्गत आता है, और न तो स्थानीय और न ही वैश्विक है - यदि आपने
x = 5
याfor x in range(3)
या किसी अन्य बंधन में पाया है, तोx
एक स्थानीय चर है - अन्यथा
x
कुछ एनक्लोजिंग स्कोप (फ़ंक्शन स्कोप, ग्लोबल स्कोप या बिलिन) के अंतर्गत आता है
स्थानीय चर
एक नाम एक समारोह के अंदर ही है, तो यह डिफ़ॉल्ट केवल समारोह में ऐक्सेस कर रहा है:
def foo():
a = 5
print(a) # ok
print(a) # NameError: name 'a' is not defined
नियंत्रण प्रवाह निर्माण का दायरा (अपवाद को except
) पर कोई प्रभाव नहीं पड़ता है, लेकिन चर को एक्सेस करना जो अभी तक असाइन नहीं किया गया है, एक त्रुटि है:
def foo():
if True:
a = 5
print(a) # ok
b = 3
def bar():
if False:
b = 5
print(b) # UnboundLocalError: local variable 'b' referenced before assignment
आम बाध्यकारी संचालन कार्य, कर रहे हैं for
इस तरह के रूप छोरों, और संवर्धित कार्य a += 5
नॉनोकॉकल वेरिएबल्स
पायथन 3 ने एक नया कीवर्ड जोड़ा, जिसे नॉनक्लॉक कहा जाता है। नॉनक्लॉक कीवर्ड आंतरिक दायरे में एक ओवरराइड जोड़ता है। आप इसके बारे में पीईपी 3104 में पढ़ सकते हैं। यह कोड उदाहरण के एक जोड़े के साथ सबसे अच्छा सचित्र है। सबसे आम उदाहरणों में से एक कार्य है कि वेतन वृद्धि कर सकते हैं:
def counter():
num = 0
def incrementer():
num += 1
return num
return incrementer
आप इस कोड को चलाने की कोशिश करें, तो आप एक UnboundLocalError क्योंकि संख्या चर से पहले ही अंतरतम समारोह में असाइन किया गया है संदर्भित है प्राप्त होगा। आइए मिश्रण में नॉनकॉक जोड़ें:
def counter():
num = 0
def incrementer():
nonlocal num
num += 1
return num
return incrementer
c = counter()
c() # = 1
c() # = 2
c() # = 3
मूल रूप से nonlocal
आपको बाहरी दायरे में चर को असाइन करने की अनुमति देगा, लेकिन वैश्विक गुंजाइश नहीं। इसलिए आप हमारे counter
फंक्शन में nonlocal
का उपयोग नहीं कर सकते हैं क्योंकि तब यह वैश्विक दायरे में जाने की कोशिश करेगा। इसे आजमाएं और आपको जल्दी ही SyntaxError
मिलेगा। इसके बजाय आपको नेस्टेड फ़ंक्शन में nonlocal
का उपयोग करना चाहिए।
(ध्यान दें कि यहां प्रस्तुत कार्यक्षमता जनरेटर का उपयोग करके बेहतर तरीके से लागू की गई है।)
बाइंडिंग घटना
x = 5
x += 7
for x in iterable: pass
उपरोक्त प्रत्येक कथन एक बाध्यकारी घटना है - x
5
द्वारा निरूपित वस्तु के लिए बाध्य हो जाता है। यदि यह कथन किसी फ़ंक्शन के अंदर दिखाई देता है, तो x
डिफ़ॉल्ट रूप से फ़ंक्शन-स्थानीय होगा। बाध्यकारी बयानों की सूची के लिए "सिंटैक्स" अनुभाग देखें।
नाम देखते समय फ़ंक्शंस क्लास स्कोप को छोड़ देते हैं
परिभाषा के दौरान कक्षाओं का एक स्थानीय क्षेत्र होता है, लेकिन कक्षा के अंदर के कार्य नाम को देखते समय उस दायरे का उपयोग नहीं करते हैं। चूँकि लैम्ब्डा फ़ंक्शन हैं, और फ़ंक्शन स्कोप का उपयोग करके समझ को लागू किया जाता है, इससे कुछ आश्चर्यजनक व्यवहार हो सकता है।
a = 'global'
class Fred:
a = 'class' # class scope
b = (a for i in range(10)) # function scope
c = [a for i in range(10)] # function scope
d = a # class scope
e = lambda: a # function scope
f = lambda a=a: a # default argument uses class scope
@staticmethod # or @classmethod, or regular instance method
def g(): # function scope
return a
print(Fred.a) # class
print(next(Fred.b)) # global
print(Fred.c[0]) # class in Python 2, global in Python 3
print(Fred.d) # class
print(Fred.e()) # global
print(Fred.f()) # class
print(Fred.g()) # global
उपयोगकर्ता इस class
काम से अपरिचित हैं जो class
प्रिंट करने के लिए b
, c
, और e
अपेक्षा कर सकता है।
वर्ग दायरे में नाम सुलभ नहीं हैं। फ़ंक्शन के दायरे को घेरने वाले अंतरतम में नामों को हल किया जाता है। यदि नेस्टेड स्कोप की एक श्रृंखला में एक वर्ग परिभाषा होती है, तो रिज़ॉल्यूशन प्रक्रिया कक्षा परिभाषाओं को छोड़ देती है।
नामकरण और बंधन पर पायथन के दस्तावेज से:
एक वर्ग ब्लॉक में परिभाषित नामों का दायरा वर्ग ब्लॉक तक सीमित है; यह विधियों के कोड ब्लॉकों तक नहीं फैलता है - इसमें एक कार्यक्षेत्र का उपयोग करके लागू किए जाने के बाद से समझ और जनरेटर अभिव्यक्तियाँ शामिल हैं। इसका मतलब है कि निम्नलिखित विफल हो जाएगा:
class A: a = 42 b = list(a + i for i in range(10))
यह उदाहरण मार्टिज़न पीटर के इस उत्तर के संदर्भों का उपयोग करता है, जिसमें इस व्यवहार का गहराई से विश्लेषण शामिल है।
द डेल कमांड
इस कमांड के कई संबंधित अलग-अलग रूप हैं।
del v
यदि v
एक वेरिएबल है, तो कमांड del v
वेरिएबल को उसके दायरे से हटा देता है। उदाहरण के लिए:
x = 5
print(x) # out: 5
del x
print(x) # NameError: name 'f' is not defined
ध्यान दें कि
del
एक बाध्यकारी घटना है , जिसका अर्थ है कि जब तक कि स्पष्ट रूप से अन्यथा (nonlocal
-global
याglobal
का उपयोग करके) नहीं कहा गया है,del v
वर्तमान दायरे मेंv
स्थानीय बना देगा। यदि आप बाहरी दायरे मेंv
को हटाना चाहते हैं, तोdel v
स्टेटमेंट के समान स्कोप मेंnonlocal v
याglobal v
उपयोग करें।
निम्नलिखित सभी में, एक कमांड का इरादा एक डिफ़ॉल्ट व्यवहार है लेकिन भाषा द्वारा लागू नहीं किया जाता है। एक वर्ग इस तरह से लिखा जा सकता है जो इस इरादे को अमान्य करता है।
del v.name
यह कमांड v.__delattr__(name)
लिए एक कॉल चलाता है।
इरादा विशेषता name
अनुपलब्ध बनाना है। उदाहरण के लिए:
class A:
pass
a = A()
a.x = 7
print(a.x) # out: 7
del a.x
print(a.x) # error: AttributeError: 'A' object has no attribute 'x'
del v[item]
यह कमांड v.__delitem__(item)
लिए एक कॉल ट्रिगर करता है।
इरादा है कि item
मानचित्रण वस्तु द्वारा कार्यान्वित में संबंधित नहीं होगा v
। उदाहरण के लिए:
x = {'a': 1, 'b': 2}
del x['a']
print(x) # out: {'b': 2}
print(x['a']) # error: KeyError: 'a'
del v[a:b]
यह वास्तव में v.__delslice__(a, b)
कहता है।
इरादा ऊपर वर्णित एक के समान है, लेकिन स्लाइस के साथ - एकल आइटम के बजाय आइटम की श्रेणियाँ। उदाहरण के लिए:
x = [0, 1, 2, 3, 4]
del x[1:3]
print(x) # out: [0, 3, 4]
कचरा संग्रह # डेल कमांड भी देखें।
लोकल बनाम ग्लोबल स्कोप
स्थानीय और वैश्विक क्षेत्र क्या हैं?
सभी पायथन वेरिएब जो किसी बिंदु पर कोड में सुलभ हैं, वे स्थानीय दायरे में या वैश्विक दायरे में हैं ।
व्याख्या यह है कि स्थानीय दायरे में वर्तमान फ़ंक्शन में परिभाषित सभी चर शामिल हैं और वैश्विक दायरे में वर्तमान फ़ंक्शन के बाहर परिवर्तनीय शामिल हैं।
foo = 1 # global
def func():
bar = 2 # local
print(foo) # prints variable foo from global scope
print(bar) # prints variable bar from local scope
एक निरीक्षण कर सकते हैं कि कौन से चर किस दायरे में हैं। बिल्ट-इन फ़ंक्शंस locals()
और globals()
पूरे स्कोप को शब्दकोशों के रूप में वापस करते हैं।
foo = 1
def func():
bar = 2
print(globals().keys()) # prints all variable names in global scope
print(locals().keys()) # prints all variable names in local scope
नाम बंद के साथ क्या होता है?
foo = 1
def func():
foo = 2 # creates a new variable foo in local scope, global foo is not affected
print(foo) # prints 2
# global variable foo still exists, unchanged:
print(globals()['foo']) # prints 1
print(locals()['foo']) # prints 2
वैश्विक चर को संशोधित करने के लिए, कीवर्ड global
उपयोग करें:
foo = 1
def func():
global foo
foo = 2 # this modifies the global foo, rather than creating a local variable
फंक्शन की पूरी बॉडी के लिए स्कोप को परिभाषित किया गया है!
इसका क्या मतलब है कि एक चर समारोह के आधे के लिए वैश्विक नहीं होगा और स्थानीय बाद में, या इसके विपरीत।
foo = 1
def func():
# This function has a local variable foo, because it is defined down below.
# So, foo is local from this point. Global foo is hidden.
print(foo) # raises UnboundLocalError, because local foo is not yet initialized
foo = 7
print(foo)
इसी तरह, ऑपोजिट:
foo = 1
def func():
# In this function, foo is a global variable from the begining
foo = 7 # global foo is modified
print(foo) # 7
print(globals()['foo']) # 7
global foo # this could be anywhere within the function
print(foo) # 7
कार्यों के भीतर कार्य
कार्यों के भीतर कई स्तर के कार्य हो सकते हैं, लेकिन किसी भी फ़ंक्शन के भीतर उस फ़ंक्शन और वैश्विक दायरे के लिए केवल एक स्थानीय गुंजाइश होती है। कोई मध्यवर्ती स्कोप नहीं हैं।
foo = 1
def f1():
bar = 1
def f2():
baz = 2
# here, foo is a global variable, baz is a local variable
# bar is not in either scope
print(locals().keys()) # ['baz']
print('bar' in locals()) # False
print('bar' in globals()) # False
def f3():
baz = 3
print(bar) # bar from f1 is referenced so it enters local scope of f3 (closure)
print(locals().keys()) # ['bar', 'baz']
print('bar' in locals()) # True
print('bar' in globals()) # False
def f4():
bar = 4 # a new local bar which hides bar from local scope of f1
baz = 4
print(bar)
print(locals().keys()) # ['bar', 'baz']
print('bar' in locals()) # True
print('bar' in globals()) # False
global
बनाम nonlocal
(केवल पायथन 3)
इन दोनों कीवर्ड का उपयोग उन चर तक पहुंच प्राप्त करने के लिए किया जाता है जो वर्तमान कार्यों के लिए स्थानीय नहीं हैं।
global
कीवर्ड घोषित करता है कि एक नाम को एक वैश्विक चर के रूप में माना जाना चाहिए।
foo = 0 # global foo
def f1():
foo = 1 # a new foo local in f1
def f2():
foo = 2 # a new foo local in f2
def f3():
foo = 3 # a new foo local in f3
print(foo) # 3
foo = 30 # modifies local foo in f3 only
def f4():
global foo
print(foo) # 0
foo = 100 # modifies global foo
दूसरी ओर, nonlocal
(देखें nonlocal चर उपलब्ध अजगर 3 में), वर्तमान समारोह के स्थानीय गुंजाइश में एक संलग्न दायरे से एक स्थानीय चर लेता है।
nonlocal
पर पायथन प्रलेखन से :
नॉनक्लॉक स्टेटमेंट में सूचीबद्ध पहचानकर्ताओं को ग्लोबल्स को छोड़कर निकटतम एन्कोडिंग दायरे में पहले से तय चर को संदर्भित करने का कारण बनता है।
def f1():
def f2():
foo = 2 # a new foo local in f2
def f3():
nonlocal foo # foo from f2, which is the nearest enclosing scope
print(foo) # 2
foo = 20 # modifies foo from f2!