2013-04-25 174 views
0

我剛剛瞭解Python的工作原理,並在閱讀了一段時間之後,仍然對全局變量和正確的函數參數感到困惑。考慮全局變量不在函數內部修改的情況,只引用。作爲函數輸入的全局變量而不是參數

可全局使用,而不是函數的參數? 我聽說過使用全局變量被認爲是不好的做法。在這種情況下會是這樣嗎?

不帶參數調用功能:帶有參數

def myfunc(arg) : 
    print arg 

myvalue = 1 
myfunc(myvalue) 
+4

你可以,但不要!顯式比隱式更好。命名空間是一個好主意 - 讓我們做更多的這些! – root 2013-04-25 12:11:15

+0

我會讀這個 - http://www.diveintopython。net/html_processing/locals_and_globals.html - 它回答你的問題100% – 2013-04-25 12:13:09

+3

它應該是一個普遍的原則,而不僅僅是在Python中,變量應該在可能的最嚴格的範圍內定義。 – 2013-04-25 12:23:01

回答

0

def myfunc() : 
    print myvalue 

myvalue = 1 
myfunc() 

調用函數。使變量global在這些情況下起作用,而不是作爲函數參數傳遞它們。但問題是,只要你開始編寫更大的函數,你很快就會用完名稱,而且很難維護全局定義的變量。如果您不需要編輯變量並只想讀取它,則不需要在函數中將其定義爲global

閱讀這裏的全局變量的缺點 - Are global variables bad?

+0

謝謝你Sukrit, 事實上,就像我上面提到的那樣。 我對主代碼中定義的任何變量調用'global'(不知道這是否正確)。 – Mike 2013-04-25 12:09:50

0

這取決於你想要做什麼。

如果您需要更改是函數的外部聲明的變量的值,那麼你不能把它作爲一個參數,因爲這將創建一個職能範圍內該變量的「複製」。
但是,如果您只想使用變量的值,則應將其作爲參數傳遞。這樣做的好處是你不能偶然搞亂全局變量。

而且在使用之前,您應該聲明全局變量。

+0

對不起,我可能沒有解釋得很好... 我的'需要'是: - 變量只在主代碼中定義並且永遠不會改變。 - 它們只能在函數中讀取,根本不能編輯。 - 「全球」聲明是neeed。 問題是爲什麼使用全局定義的變量而不是函數參數被認爲是不好的做法。我認爲Sukrit可能是正確的,當他說問題出現時,功能變得更大...... – Mike 2013-04-25 12:24:54

+1

如果這些值nevery改變,那麼在腳本開始時定義它們一次並不錯,然後在函數內部簡單地訪問它們。通常這些常數必須與所有的大寫字母名稱綁定,例如IP =「10.122.10.12」 – pypat 2013-04-25 12:27:34

+1

@Mike - pypat是正確的 - 如果您在程序開始時聲明瞭基本的常量,並且它們永不改變,那麼可以使用它們。但是它們應該用大寫字母表示,所以與其他變量有明顯的區別。如果他們在整個計劃中更換一次,則不應該這樣做。 – root 2013-04-25 12:40:59

2

我聽說過使用全局變量被認爲是不好的做法。在這種情況下會是這樣嗎?

這取決於你想要達到的目的。如果myfunc()應該打印任何值,那麼......

def myfunc(arg): 
    print arg 

myfunc(1) 

...比較好,但如果myfunc()應該總是打印相同的值,然後...

myvalue = 1 

def myfunc(): 
    print myvalue 

myfunc() 

...是好,雖然用一個例子就這麼簡單,你不妨分解出全球性的,只是用...

def myfunc(): 
    print 1 

myfunc() 
+0

好吧,如果一個函數總是返回相同的東西,它是否應該是一個函數是值得懷疑的... – root 2013-04-25 12:21:44

0

有幾個原因,使用函數的參數是不是U更好唱全局:

  1. 它消除了可能的混淆:一旦你的程序變大了,將很難跟蹤哪個全球使用在哪裏。傳遞函數參數可讓您更清楚地瞭解函數使用哪些值。
  2. 有一個特別的錯誤,你將最終如果你使用全局變量,這會顯得非常奇怪直到你明白這是怎麼回事。它與修改和讀取同一函數中的全局變量有關。稍後再說。
  3. 全局變量都存在於同一個命名空間中,因此您將很快遇到重疊名稱的問題。如果你想要兩個名爲「index」的不同變量呢?打電話給他們index1index2會變得非常混亂,真正快速。使用局部變量或函數參數意味着它們全都位於不同的命名空間中,混淆的可能性大大降低。

現在,我提到在相同的函數中修改和讀取一個全局變量,並且可能導致一個令人困惑的錯誤。這裏是什麼樣子:

record_count = 0 # Global variable 
def func(): 
    print "Record count:", record_count 
    # Do something, maybe read a record from a database 
    record_count = record_count + 1 # Would normally use += 1 here, but it's easier to see what's happening with the "n = n + 1" syntax 

這將失敗:UnboundLocalError: local variable 'record_count' referenced before assignment

等等,什麼?爲什麼record_count被視爲局部變量,當它顯然是全球性的?那麼,如果你的函數中沒有分配record_count,那麼Python會使用全局變量。但是當你給record_count賦值時,Python必須猜測你的意思:你是想修改全局變量,還是想創建一個新的局部變量來隱藏(隱藏)全局變量,只處理局部變量。 Python會默認假設你對全局變得很聰明(即不知道正好你在做什麼以及爲什麼不修改它們),並且假設你想創建一個名爲record_count的新局部變量。

但是,如果您在函數內部訪問名爲record_count的本地變量,那麼Python不會讓您訪問函數內具有相同名稱的全局變量。這是爲了讓你真正地知道討厭的,難以追蹤的錯誤。這意味着如果該函數有一個本地變量名爲record_count - 並且它的確由於賦值語句 - 那麼全部訪問record_count被認爲是訪問本地變量。 包括print語句中的訪問,在定義局部變量的值之前。因此,UnboundLocalError異常。

現在,給讀者一個練習。刪除打印語句並注意UnboundLocalError例外是仍然拋出。你能弄清楚爲什麼? (提示:分配給一個變量之前,對分配的右手邊的值必須計算。)

現在:如果你真的要使用全局record_count變量在功能,方式這是Python的global聲明,其中說:「嘿,這個變量名我要指定?不要把它作爲局部變量,即使我分配給它,而是分配給全局變量。」在你的函數開始時,它的工作方式只是global record_count(或任何其他變量名稱)。因此:

record_count = 0 # Global variable 
def func(): 
    global record_count 
    print "Record count:", record_count 
    # Do something, maybe read a record from a database 
    record_count = record_count + 1 # Again, you would normally use += 1 here 

這將做你想要的東西。但希望你現在明白爲什麼它會工作,而其他版本不會。