पायथन में "वैश्विक" कीवर्ड का उपयोग


285

दस्तावेज़ीकरण पढ़ने से मुझे जो समझ में आया वह यह है कि पायथन के कार्यों के लिए एक अलग नामस्थान है, और यदि मैं उस फ़ंक्शन में एक वैश्विक चर का उपयोग करना चाहता हूं, तो मुझे उपयोग करने की आवश्यकता है global

मैं पायथन 2.7 का उपयोग कर रहा हूं और मैंने इस छोटे परीक्षण की कोशिश की

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

ऐसा लगता है कि चीजें बिना भी ठीक काम कर रही हैं global। मैं किसी भी समस्या के बिना वैश्विक चर का उपयोग करने में सक्षम था।

क्या मुझे कुछ याद आ रहा है? इसके अलावा, पायथन प्रलेखन से निम्नलिखित है:

वैश्विक कथन में सूचीबद्ध नामों को औपचारिक मापदंडों के रूप में या लूप नियंत्रण लक्ष्य, वर्ग परिभाषा, फ़ंक्शन परिभाषा या आयात विवरण के रूप में परिभाषित नहीं किया जाना चाहिए।

जबकि औपचारिक पैरामीटर और वर्ग परिभाषा मेरे लिए मायने रखती है, मैं लूप नियंत्रण लक्ष्य और फ़ंक्शन परिभाषा के लिए प्रतिबंध को समझने में सक्षम नहीं हूं।


1
मुझे लगता है कि आप php से भ्रमित हैं, जिसके लिए वैश्विक कीवर्ड के उपयोग की आवश्यकता है - अजगर डॉक्स इसकी पुष्टि करते हैं - मूल रूप से अगर इसे स्थानीय संदर्भ में परिभाषित नहीं किया जाता है तो इसे वैश्विक माना जाता है
tobyodavies

11
अपने शब्दों के साथ सावधान रहें: पायथन में कार्यों के लिए एक अलग नाम स्थान नहीं है (इसका मतलब होगा कि आप एक ही समय में def foo(): ...और हो सकते हैं foo = ...)। यह हर फ़ंक्शन कॉल के लिए एक नया स्कोप बनाता है। (लेकिन यह दुनिया के हर दूसरे दूरस्थ उच्च-स्तरीय भाषा से अलग कैसे है?)

जवाबों:


366

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

def bob():
    me = "locally defined"    # Defined only in local context
    print(me)

bob()
print(me)     # Asking for a global variable

ऊपर आपको दे देंगे:

locally defined
Traceback (most recent call last):
  File "file.py", line 9, in <module>
    print(me)
NameError: name 'me' is not defined

यदि आप globalकथन का उपयोग करते हैं , तो चर फ़ंक्शन के दायरे से "बाहर" उपलब्ध हो जाएगा, प्रभावी रूप से एक वैश्विक चर बन जाएगा।

def bob():
    global me
    me = "locally defined"   # Defined locally but declared as global
    print(me)

bob()
print(me)     # Asking for a global variable

तो उपरोक्त कोड आपको देगा:

locally defined
locally defined

इसके अलावा, अजगर की प्रकृति के कारण, आप globalस्थानीय संदर्भ में कार्यों, कक्षाओं या अन्य वस्तुओं को घोषित करने के लिए भी उपयोग कर सकते हैं । यद्यपि मैं इसके खिलाफ सलाह दूंगा क्योंकि यह बुरे सपने का कारण बनता है अगर कुछ गलत हो जाता है या डिबगिंग की आवश्यकता होती है।


59
इस संदर्भ में "वैश्विक" अन्य भाषाओं से भिन्न प्रतीत होता है जो "वैश्विक" मानते हैं। पायथन में एक "वैश्विक" संदर्भ अभी भी मॉड्यूल की परिधि में है और इसे उस मॉड्यूल से बाहर से संदर्भित करने की आवश्यकता होगी जैसे कि "global_var" के बजाय "mod.global_var" के रूप में एक हो सकता है।
जूस

17
@ ज्यूस - पायथन globalsमें सभी नामस्थानों (धन्यवाद) के रूप में निरपेक्ष रूप से परिभाषित कोई चीज नहीं है । जैसा कि आपने सही ढंग से बताया है, एक मॉड्यूल के भीतर एक वैश्विक नाम स्थान से जुड़ा होता है, हालांकि इसे किसी अन्य मॉड्यूल में from module import variableया के रूप में आयात किया जा सकता है import module.variable। पहले मामले में, आयात को variableसंदर्भ की आवश्यकता के बिना चर को सुलभ बनाना होगा module.। यदि इसे मॉड्यूल के दायरे में एक वैश्विक माना जाता है, तो यह इस बात पर निर्भर करेगा कि यह कहाँ आयात किया गया है। nonlocalअजगर 3 में एक नए स्कोप से संबंधित कीवर्ड के रूप में भी देखें
17

3
क्या आप बता सकते हैं कि वैश्विक चर एक अच्छा समाधान क्यों नहीं हैं? मैं अक्सर यह सुनता हूं, लेकिन मेरी वर्तमान परियोजना में वे वही करते हैं जो मुझे करने की आवश्यकता है। वहाँ कुछ और अधिक भयावह मैं के बारे में सोचा नहीं है?
रॉबिन न्यूहाउस

5
@RobinNewhouse एसओ पर कुछ सवाल हैं जो पहले से ही उस विषय और अन्य गैर एसओ लेखों को कवर कर रहे हैं
unode

213

जब आप globalकीवर्ड के बिना वैश्विक चर का उपयोग कर सकते हैं , यदि आप उन्हें संशोधित करना चाहते हैं तो आपको globalकीवर्ड का उपयोग करना होगा । उदाहरण के लिए:

foo = 1
def test():
    foo = 2 # new local foo

def blub():
    global foo
    foo = 3 # changes the value of the global foo

आपके मामले में, आप केवल सूची तक पहुंच रहे हैं sub


3
एक चेतावनी के साथ: foo = 3वैश्विक कार्यों के बिना, लेकिन फू को स्थानीय रूप से blubकार्य क्षेत्र में फिर से परिभाषित किया गया है और मूल फू चर को संशोधित नहीं करता है। यह मेरे लिए काफी उलझन भरा था।
छन्नीलाल

1
@chhantyal अगर काम करता है, तो इसका मतलब है कि यह एक त्रुटि नहीं है, आप सही हैं, लेकिन इवो वेटज़ेल के संदर्भ में यह उद्देश्य के अनुसार काम नहीं करेगा। इस तरह के व्यवहार के लिए उपयोग होते हैं, लेकिन यह अक्सर ऐसा नहीं होता है जो प्रोग्रामर चाहता है।
लोकतंत्रवादी

77

यह नाम तक पहुंचने और इसे एक दायरे में बांधने के बीच का अंतर है ।

यदि आप इसके मूल्य को पढ़ने के लिए केवल एक चर की तलाश कर रहे हैं, तो आपको वैश्विक और साथ ही स्थानीय दायरे तक पहुंच मिल गई है।

हालाँकि यदि आप एक ऐसे चर को असाइन करते हैं जिसका नाम स्थानीय दायरे में नहीं है, तो आप उस नाम को इस दायरे में बाँध रहे हैं (और यदि वह नाम वैश्विक रूप में भी मौजूद है, तो आप उसे छिपा देंगे)।

यदि आप वैश्विक नाम को निर्दिष्ट करने में सक्षम होना चाहते हैं, तो आपको पार्सर को एक नए स्थानीय नाम को बांधने के बजाय वैश्विक नाम का उपयोग करने की आवश्यकता है - जो कि 'वैश्विक' कीवर्ड करता है।

एक ब्लॉक के भीतर कहीं भी बांधने से उस ब्लॉक में हर जगह नाम बंध जाता है, जिससे कुछ अजीब दिखने वाले परिणाम हो सकते हैं (जैसे अनबाउंडलोक्योर अचानक अचानक काम करने वाले कोड में दिखाई देना)।

>>> a = 1
>>> def p():
    print(a) # accessing global scope, no binding going on
>>> def q():
    a = 3 # binding a name in local scope - hiding global
    print(a)
>>> def r():
    print(a) # fail - a is bound to local scope, but not assigned yet
    a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    r()
  File "<pyshell#32>", line 2, in r
    print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>> 

बहुत ही
स्पष्टवादी,

52

अन्य उत्तर आपके प्रश्न का उत्तर देते हैं। पायथन में नामों के बारे में जानने के लिए एक और महत्वपूर्ण बात यह है कि वे या तो स्थानीय या वैश्विक हैं, प्रति-कार्यक्षेत्र आधार पर।

इस पर विचार करें, उदाहरण के लिए:

value = 42

def doit():
    print value
    value = 0

doit()
print value

आप शायद अनुमान लगा सकते हैं कि value = 0बयान एक स्थानीय चर को असाइन करेगा और doit()फ़ंक्शन के बाहर घोषित समान चर के मूल्य को प्रभावित नहीं करेगा । आपको यह जानकर और अधिक आश्चर्य हो सकता है कि ऊपर का कोड नहीं चलेगा। print valueफ़ंक्शन के अंदर का स्टेटमेंट एक उत्पादन करता हैUnboundLocalError.

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


1
इस पर ध्यान दिलाने के लिए धन्यवाद। इसलिए, जब तक कि आपका स्थानीय दायरा एक ऐसे नाम को निर्दिष्ट नहीं करता है जो इसके बाहर मौजूद है, तब तक स्थानीय दायरे में संदर्भ बाहरी नाम का उपयोग करेगा। हालाँकि, यदि आपके फ़ंक्शन में कहीं भी आप उस नाम को निर्दिष्ट करते हैं, तो स्थानीय असाइनमेंट से पहले भी, उस स्थानीय क्षेत्र में संदर्भ, बाहर न देखें।
दिमित्री मिन्कोवस्की

1
वास्तव में, आपको मिल गया है। global(या nonlocalपायथन 3.x में) इस व्यवहार को ओवरराइड करता है और आपको बाहरी नाम को फिर से असाइन करने की अनुमति देता है।
किन्नर

2
अन्य भाषाओं में, इसे "उत्थापन" के रूप में जाना जाता है, उदाहरण के लिए इस तरह: github.com/shichuan/javascript-patterns/blob/master/…
दिमित्री मिनकोवस्की

चोट के अपमान जोड़ने के लिए, चर नए जावास्क्रिप्ट कीवर्ड के साथ घोषित letकर रहे हैं नहीं फहराया।
किंडल

क्या इसके साथ घोषित किए गए वैश्विक चर का उपयोग करना तेज़ है globalया इससे कोई फर्क नहीं पड़ता?
Mato

14

एक नाम एक्सेस करना और एक नाम निर्दिष्ट करना अलग हैं। आपके मामले में, आप केवल एक नाम तक पहुंच रहे हैं।

यदि आप किसी फ़ंक्शन के भीतर एक वैरिएबल को असाइन करते हैं, तो उस वैरिएबल को स्थानीय माना जाता है जब तक कि आप इसे वैश्विक घोषित नहीं करते। इसके अभाव में, यह वैश्विक माना जाता है।

>>> x = 1         # global 
>>> def foo():
        print x       # accessing it, it is global

>>> foo()
1
>>> def foo():   
        x = 2        # local x
        print x 

>>> x            # global x
1
>>> foo()        # prints local x
2

7
  • आप बिना कीवर्ड के ग्लोबल कीवर्ड एक्सेस कर सकते हैं global
  • उन्हें संशोधित करने में सक्षम होने के लिए आपको यह स्पष्ट रूप से बताने की आवश्यकता है कि कीवर्ड वैश्विक है। अन्यथा, कीवर्ड को स्थानीय दायरे में घोषित किया जाएगा।

उदाहरण:

words = [...] 

def contains (word): 
    global words             # <- not really needed
    return (word in words) 

def add (word): 
    global words             # must specify that we're working with a global keyword
    if word not in words: 
        words += [word]

2

किसी फ़ंक्शन के बाहर घोषित किया गया कोई भी वैरिएबल वैश्विक माना जाता है, यह तभी होता है जब उन्हें फ़ंक्शन (निर्माणकर्ताओं को छोड़कर) के अंदर से घोषित किया जाता है कि आपको यह निर्दिष्ट करना होगा कि वैरिएबल वैश्विक हो।


1

इसे पायथन एफएक्यू में अच्छी तरह से समझाया गया है

पायथन में स्थानीय और वैश्विक चर के लिए नियम क्या हैं?

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

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

https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python


0

इसका अर्थ है कि आपको निम्न कार्य नहीं करने चाहिए:

x = 1

def myfunc():
  global x

  # formal parameter
  def localfunction(x):
    return x+1

  # import statement
  import os.path as x

  # for loop control target
  for x in range(10):
    print x

  # class definition
  class x(object):
    def __init__(self):
      pass

  #function definition
  def x():
    print "I'm bad"

ikostia उन सभी चीजों की गणना कर रहा है जिनका आप वैश्विक उपयोग के लिए 'x' का उपयोग नहीं कर सकते हैं - docs.python.org/reference/…
pycruft

1
@ यूनोड: मैं सिर्फ उन सभी मामलों का प्रदर्शन कर रहा हूं जो निखिलराठोड ने अपने उद्धरण में दिए थे।
.हस्तिया

0

वैश्विक परिवर्तनशील बनाता है "ग्लोबल"

def out():
    global x
    x = 1
    print(x)
    return


out()

print (x)

यह 'x' फंक्शन के बाहर एक सामान्य वेरिएबल की तरह कार्य करता है। यदि आपने ग्लोबल को बाहर कर दिया है तो यह एक त्रुटि देगा क्योंकि यह किसी फ़ंक्शन के अंदर एक वैरिएबल को प्रिंट नहीं कर सकता है।

def out():
     # Taking out the global will give you an error since the variable x is no longer 'global' or in other words: accessible for other commands
    x = 1
    print(x)
    return


out()

print (x)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.