पायथन फ़ंक्शन वैश्विक चर?


271

मुझे पता है कि मुझे इस तरह के भ्रम के कारण पहली बार में वैश्विक चर का उपयोग करने से बचना चाहिए, लेकिन अगर मैं उनका उपयोग करना था, तो उनका उपयोग करने के बारे में जाने के लिए एक वैध तरीका निम्नलिखित है? (मैं एक अलग फ़ंक्शन में बनाए गए चर की वैश्विक प्रतिलिपि को कॉल करने का प्रयास कर रहा हूं।)

x = "somevalue"

def func_A ():
   global x
   # Do things to x
   return x

def func_B():
   x = func_A()
   # Do things
   return x

func_A()
func_B()

क्या जो xदूसरा फ़ंक्शन उपयोग करता है, xउसके func_aउपयोग और संशोधित की वैश्विक प्रतिलिपि का समान मूल्य है? परिभाषा के बाद फ़ंक्शन को कॉल करते समय, क्या आदेश होता है?


1
यह भी ध्यान रखें कि सिर्फ इसलिए नहीं कि आपके पास अपने फ़ंक्शन में एक चर है जिसे अजगर असाइनमेंट से पहले संदर्भों के साथ व्यवहार करेगा। पहले असाइनमेंट तक, यदि आपने x का उपयोग किया है, तो यह वैश्विक एक या स्थानीय नहीं होगा। आप अपने चेहरे में कुख्यात UnboundLocalError अपवाद प्राप्त करेंगे :)
osirisgothra

जवाबों:


412

यदि आप एक वैश्विक चर का उपयोग करना चाहते हैं, तो आप सिर्फ उसके नाम का उपयोग करें। हालाँकि इसके मूल्य को बदलने के लिए आपको globalकीवर्ड का उपयोग करना होगा ।

उदाहरण के लिए

global someVar
someVar = 55

यह वैश्विक चर के मूल्य को 55 में बदल देगा। अन्यथा यह केवल 55 को एक स्थानीय चर को असाइन करेगा।

फंक्शन डेफिनिशन लिस्टिंग का क्रम मायने नहीं रखता (यह मानते हुए कि वे एक दूसरे को किसी तरह से संदर्भित नहीं करते हैं), जिस क्रम को वे कहते हैं।


2
मेरे द्वारा दिए गए कोड में, x की वैश्विक प्रति के लिए func_B कर रही चीजें (1) है (जैसे func_A से प्राप्त), (2) func_A, या (3) के परिणाम के समान मान के साथ स्थानीय चर x के लिए एक स्थानीय चर x जिसका कोई मूल्य नहीं है और (संकलक की नजर में) "कुछ मूल्य" या x का कोई संबंध नहीं है func_A में?
अक्षत शेखर

xमें func_Bएक स्थानीय वैरिएबल है जो कॉल के रिटर्न मूल्य से अपना मूल्य प्राप्त करता है func_A- इसलिए मुझे लगता है कि यह आपके (2)
लेवोन

ठीक है, मान लीजिए कि x फंक_ए द्वारा उत्पन्न कुछ प्रकार का एक यादृच्छिक अनुक्रम था (यानी कि func_A ने हर बार चलाने के दौरान एक अलग एक्स का उत्पादन किया था।) प्रोग्राम को चलाएगा जैसा कि लिखा गया है func_b एक अलग एक्स को संशोधित करें जो मूल रूप से func_a द्वारा निर्मित था। बुलाया? यदि हां, तो मैं इसे कैसे ठीक कर सकता हूं?
अक्षत शेखर

1
हां, यदि func_Aप्रत्येक रन के दौरान वैश्विक चर बदलता है और इसका func_Bउपयोग करने के लिए वापस लौटाता है , तो func_Bहर बार बदले मूल्य के साथ काम करेगा। मुझे आपके "कैसे ठीक करना है" के बारे में निश्चित नहीं है। आप अपने वर्तमान / मूल प्रश्न के सबसे उपयोगी उत्तर को स्वीकार करना चाहते हैं और फिर एक अनुवर्ती प्रश्न की तरह दिखने वाले एक अलग प्रश्न को खोलने पर विचार कर सकते हैं।
लेवोन

1
वास्तव में यह निर्भर करता है कि x क्या है। यदि x अपरिवर्तनीय है, तो func_B में x इसमें रहेगा, क्योंकि यह स्थानीय रूप से घोषित किया गया है, भले ही उनका मूल्य समान हो। यह tuples, ints पर लागू होता है ... यदि यह उदाहरण के लिए एक सूची का एक उदाहरण है और आप करते हैं x.append("..."), तो यह वैश्विक चर x है जिसे बदल दिया जाता है, क्योंकि स्थानीय एक वैश्विक संदर्भ देता है।
jadkik94

110

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

आइए देखें कि क्या होता है देखने के लिए अपने छद्मकोड के एक संशोधित संस्करण को देखें:

# Here, we're creating a variable 'x', in the __main__ scope.
x = 'None!'

def func_A():
  # The below declaration lets the function know that we
  #  mean the global 'x' when we refer to that variable, not
  #  any local one

  global x
  x = 'A'
  return x

def func_B():
  # Here, we are somewhat mislead.  We're actually involving two different
  #  variables named 'x'.  One is local to func_B, the other is global.

  # By calling func_A(), we do two things: we're reassigning the value
  #  of the GLOBAL x as part of func_A, and then taking that same value
  #  since it's returned by func_A, and assigning it to a LOCAL variable
  #  named 'x'.     
  x = func_A() # look at this as: x_local = func_A()

  # Here, we're assigning the value of 'B' to the LOCAL x.
  x = 'B' # look at this as: x_local = 'B'

  return x # look at this as: return x_local

वास्तव में, आप func_Bनामांकित चर के साथ सभी को फिर से लिख सकते हैं x_localऔर यह पहचान के साथ काम करेगा।

यह आदेश केवल उस स्थिति के लिए मायने रखता है जहां तक ​​कि आपके कार्य ऐसे ऑपरेशन करते हैं जो वैश्विक x के मान को बदलते हैं। इस प्रकार, func_Bकॉल के बाद से हमारे उदाहरण में, कोई फर्क नहीं पड़ता func_A। इस उदाहरण में, आदेश मायने रखता है:

def a():
  global foo
  foo = 'A'

def b():
  global foo
  foo = 'B'

b()
a()
print foo
# prints 'A' because a() was the last function to modify 'foo'.

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

x = 5

def access_only():
  return x
  # This returns whatever the global value of 'x' is

def modify():
  global x
  x = 'modified'
  return x
  # This function makes the global 'x' equal to 'modified', and then returns that value

def create_locally():
  x = 'local!'
  return x
  # This function creates a new local variable named 'x', and sets it as 'local',
  #  and returns that.  The global 'x' is untouched.

अंतर नोट के बीच create_locallyऔर access_only- access_onlyना बुलाने के बावजूद वैश्विक एक्स तक पहुँच रहा है global, और भले ही create_locallyउपयोग नहीं करता है globalया तो, यह एक स्थानीय प्रतिलिपि के बाद से यह है बनाता बताए एक मूल्य।

यहां भ्रम यह है कि आपको वैश्विक चर का उपयोग क्यों नहीं करना चाहिए।


2
मुझे नहीं लगता कि यह बहुत भ्रमित करने वाला अभ्यास है, आपको बस अजगर के डांटने के नियमों को समझना होगा ।
केसी कुबाल

20

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

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

कई ऑब्जेक्ट जो किसी ऑब्जेक्ट को संशोधित (म्यूट) करते हैं, वैश्विक नाम को किसी अलग ऑब्जेक्ट को इंगित करने के लिए फिर से बाँध नहीं करते हैं , और इसलिए वे फ़ंक्शन में नाम घोषित किए बिना सभी मान्य हैं global

d = {}
l = []
o = type("object", (object,), {})()

def valid():     # these are all valid without declaring any names global!
   d[0] = 1      # changes what's in d, but d still points to the same object
   d[0] += 1     # ditto
   d.clear()     # ditto! d is now empty but it`s still the same object!
   l.append(0)   # l is still the same list but has an additional member
   o.test = 1    # creating new attribute on o, but o is still the same object

8

यहां एक मामला है जो मुझे पकड़ा गया है, एक पैरामीटर के डिफ़ॉल्ट मान के रूप में एक वैश्विक का उपयोग करते हुए।

globVar = None    # initialize value of global variable

def func(param = globVar):   # use globVar as default value for param
    print 'param =', param, 'globVar =', globVar  # display values

def test():
    global globVar
    globVar = 42  # change value of global
    func()

test()
=========
output: param = None, globVar = 42

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

def func(param = eval('globVar')):       # this seems to work
    print 'param =', param, 'globVar =', globVar  # display values

या, यदि आप सुरक्षित रहना चाहते हैं,

def func(param = None)):
    if param == None:
        param = globVar
    print 'param =', param, 'globVar =', globVar  # display values

इसने मुझे एक खाली सूची को डिफ़ॉल्ट मान के रूप में निर्दिष्ट करने की समस्या की याद दिला दी । और, उदाहरण के लिए, सामान्य तुलना के बजाय isअगर कुछ है None, तो यह जांचने के लिए उपयोग करें ==
berna1111

6

आप सीधे एक फ़ंक्शन के अंदर एक वैश्विक चर का उपयोग कर सकते हैं। यदि आप उस वैश्विक चर का मान बदलना चाहते हैं, तो "global variable_name" का उपयोग करें। निम्नलिखित उदाहरण देखें:

var = 1
def global_var_change():
      global var
      var = "value changed"
global_var_change() #call the function for changes
print var

सामान्यतया, यह एक अच्छा प्रोग्रामिंग अभ्यास नहीं है। नेमस्पेस लॉजिक को तोड़कर, कोड को समझना और डीबग करना मुश्किल हो सकता है।


2

globalजब आप वैश्विक वैरिएबल को निर्दिष्ट मान को बदलना चाहते हैं तो आपको घोषणा का उपयोग करना चाहिए ।

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


2
यह शब्दांकन दुर्भाग्यपूर्ण है। पायथन में, एक चर के लिए दिया गया मान एक संदर्भ है, इसलिए यह तकनीकी रूप से सही है (और मुझे इसमें कोई संदेह नहीं है कि आपका मतलब क्या है), लेकिन कई पाठक "वस्तु को बदलने" के रूप में "मूल्य में परिवर्तन" की व्याख्या कर सकते हैं, जो नहीं है मामला - xs.append(xs.pop(0))बिना ठीक काम करता है global xs

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