2012-05-14 16 views
176

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

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 कि func_a उपयोग करता है और संशोधित की वैश्विक प्रतिलिपि की एक ही मूल्य है x करता है? परिभाषा के बाद कार्यों को बुलाते समय, आदेश मायने रखता है?

+0

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

उत्तर

267

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

उदा।

global someVar 
someVar = 55 

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

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

+2

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

+0

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

+0

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

0

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

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

+2

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

+0

@delnan मेरा जवाब सावधानीपूर्वक शब्दों में है, लेकिन मैं स्पष्ट कर दूंगा। – Marcin

12

जैसा कि अन्य ने ध्यान दिया है, आपको उस फ़ंक्शन में एक चर 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 
65

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

आइए नज़र देखने के लिए कि क्या होता है:

# 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 

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

ऑर्डर केवल तभी महत्वपूर्ण है जब आपके कार्य संचालन करते हैं जो वैश्विक x के मान को बदलते हैं। इस प्रकार हमारे उदाहरण में, आदेश कोई फर्क नहीं पड़ता, क्योंकि func_Bfunc_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_locallyglobal या तो उपयोग नहीं करता है, यह बाद से स्थानीय प्रतिलिपि बनाता है यह एक मान है एक मान।

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

+0

मुझे नहीं लगता कि यह अभ्यास में बहुत भ्रमित है, आपको बस [पायथन के स्कॉइंग नियम] को समझना होगा (http://stackoverflow.com/questions/291978/short-description-of-python-scoping- नियम)। – Darthfett

2

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

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 के मान का मूल्यांकन किया जब पहली बार फ़ंक्शन func को पार्स किया गया। GlobVar के मान को बदलने से param को असाइन किए गए डिफ़ॉल्ट मान को प्रभावित नहीं किया गया था। मूल्यांकन में देरी, जैसा कि निम्नलिखित में किया गया था, जैसा कि मुझे इसकी आवश्यकता थी।

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 
0

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

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

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

संबंधित मुद्दे