2012-05-14 530 views
176

我知道我應該首先避免使用全局變量,因爲這樣的混淆,但如果我要使用它們,下面是使用它們的有效方法嗎? (我想打電話給一個單獨的函數創建一個變量的全球複印件)。Python函數全局變量?

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第二函數使用有xfunc_a使用和修改全局複製相同的值?定義後調用函數時,命令是否重要?

+0

還要小心,不要因爲你的函數中分配了一個變量而認爲python會在賦值之前對待引用。在第一次分配之前,如果你使用x,它不會是全局的,或者是本地的。你會在你的臉上得到臭名昭着的UnboundLocalError異常:) – osirisgothra

回答

267

如果你想簡單地訪問一個全局變量,你只需要使用它的名字。然而要更改其值你需要使用global關鍵字。

E.g.

global someVar 
someVar = 55 

這會將全局變量的值更改爲55,否則它只會將55賦值給局部變量。

的函數定義列表無關緊要(假設他們沒有提及對方以某種方式)的順序,他們被稱爲順序一樣。

+2

在我給出的代碼中,func_B將事物(1)全局複製到x(從func_A獲得),(2)到一個局部變量x func_A的結果相同的值,或者(3)與沒有值和(在編譯器眼中)與局部變量x沒有關係的「某個值」或func_A中的x? –

+0

'func_B'中的'x'是一個局部變量,它從調用返回值'func_A'獲取它的值 - 所以我想這會使它成爲你的(2) – Levon

+0

ok,假設x是隨機序列由func_A生成的某種類型(即func_A每次運行時都會生成一個不同的x)。運行程序時會如何寫func_b修改與調用func_a時最初生成的x不同的x?如果是這樣,我該如何解決它? –

0

當你想改變分配到一個全局變量的值必須使用global聲明。

你不需要它從一個全局變量讀取。請注意,在對象上調用方法(即使它改變了該對象中的數據)並不會改變保存該對象的變量的值(缺少反射魔法)。

+2

這種措辭是不幸的。在Python中,分配給變量的值是一個引用,所以它在技術上是正確的(我毫不懷疑你的意思),但是很多讀者可能會將「改變值」解釋爲「改變對象」,而不是案例 - '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

在一個Python範圍,任何分配到該範圍內沒有聲明的變量創建一個新的局部變量除非變量早在函數聲明爲指的是全球範圍變量與關鍵字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 

事實上,你可以用一個名爲x_local變量重寫所有的func_B,它將相同的工作。

該命令僅與您的函數執行改變全局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_locallyaccess_only之間的區別 - 儘管沒有要求globalaccess_only正在訪問全局X,即使create_locally不使用global或者,它會創建一個本地副本,因爲它的分配一個值。

這裏的困惑是爲什麼你不應該使用全局變量。

+0

我不認爲這是在實踐中很混亂,你只需要瞭解[python的範圍規則](http://stackoverflow.com/questions/291978/short-description-of-python-scoping-rules)。 – 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.驚喜。 Python 2.7在首次分析函數func時評估了globVar的值。更改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 

一般來說,這不是一個好的編程習慣。通過打破命名空間邏輯,代碼可能變得難以理解和調試。