2010-10-01 78 views
1

我有一個關於Python中的全局變量的問題。 代碼如下。如果我在功能測試中不使用全局M, 會發生錯誤。 但它爲什麼不顯示字符串s的錯誤。我不把它聲明爲全球性的。python字符串是默認全局的

global M 
M = [] 
s = "abc" 

def test(): 
    ### global M 
    print M 
    M.append(s) 

打印中號 UnboundLocalError:分配

+1

請包括您得到的錯誤消息的文本。 – 2010-10-01 14:59:26

+0

感謝您幫助格式化代碼。 – chnet 2010-10-01 14:59:47

+1

如果您發佈更多關於您嘗試解決的問題,我們可能會找到一個很好的方法來分解它,以便您不需要使用全局變量。相信我,你不想這樣做。也許發佈另一個問題,因爲「我怎樣才能重構此代碼來擺脫全局...」 – Daenyth 2010-10-01 15:18:33

回答

2

之前引用局部變量「M」,我不太清楚你會得到什麼樣的錯誤,但你似乎可以用全球的錯。

聲明全局變量不需要(或建議)全局關鍵字。它被用在函數內部來指定不應該創建局部變量。考慮2個不同的功能:

M = [] 

def test1(): 
    M = [1] 

def test2(): 
    global M 
    M = [2] 

test1的將創建一個新的局部變量,而TEST2將寫入全球併購

6

If I do not use global M in function test, It would issue error.

你的這種說法是根本不真正

>>> M = [] 
>>> s = "abc" 
>>> 
>>> def test(): 
...  M.append(s) 
... 
>>> M 
[] 
>>> test() 
>>> M 
['abc'] 

我想你混淆了兩個完全和完全不同的概念:

  1. 結合barename - 通過一些其他的通常是由分配(即=),還可能 語句(def,& C)

  2. 調用一個方法(S UCH作爲append),該「可」發生變異對象 (僅當該對象是可變的,並且該方法當然是一個增變,但 不會應用於當對象是一個列表,並且該方法是append

我不確定人們爲什麼會混淆兩極分離的概念,但他們肯定可以。也許這是事實,一些非純粹的香草「種」的任務實際上是「幕後」調用一種(特殊)方法,例如,分配給合格的名字(a.b=c實際上是調用type(a).__setitem__(a, b),所以,調用方法,而不是重新綁定任何裸號)和增加的賦值(a+=b實際上是做a = type(a).__iadd__(a, b),所以,調用方法重新綁定一個裸號)。

你需要global(唉),當且僅當你正在做的「1」:重新綁定一個barename(包括增量賦值但包括任何其它特殊情況下重新綁定的話)。除非它真的不可或缺(並且很多人會說它從來不是真的不可或缺......只是「在某些情況下顯然有點方便」);-)。

+0

當我把「在「M.append(s)」之前打印M「。 – chnet 2010-10-01 15:17:31

+2

@chnet請將錯誤信息複製到您的問題中,而不是隻是在談論它。你迫使人們閱讀你的思想,這不起作用。 – 2010-10-01 15:21:36

+0

@chnet,在我的答案中給出的代碼片段中的函數test中添加一個'print M'語句就好了,所以,_again_,你的語句只是錯誤的。你的代碼必須與上述內容有重大區別,並且我們不可能猜測可能存在哪些差異,因爲你將代碼隱藏起來並做出錯誤陳述,而不是**向我們展示代碼**! - ) – 2010-10-01 15:30:46

0

由於@Alex馬爾泰利指出你的代碼所示不會產生錯誤,但將是,除了現在的基礎上@ cobbal的回答(對不起,我不能評論還)你需要非常小心當說到這裏

範圍在@ cobbal的回答是:

def test1(): 
    M = [1] 

創建一個新的變量M函數的局部test1。但是,如果不是在執行任務M = [1],而是使用M.append(1)(如問題中所做的那樣),而不是創建新的局部變量,Python會從函數的本地範圍查找更高範圍,在這種情況下,全局範圍確實已經有一個指向空列表的變量M。在這種情況下,Python會找到這個變量並簡單地附加到現有列表中,導致全局M現在指向[1]

在第二個例子:

def test2(): 
    global M 
    M = [2] 

使用該global關鍵字是必要的,以避免否則會發生的本地分配。通過調用global使用M在本地範圍內的函數將指向已有的[]對象的函數外部。

您可以通過在函數的各種形式中插入id(M)來證明這一點,以顯示哪些實現會導致函數內部的M指向全局對象或本地對象。