全局變量 大寫java
局部變量 小寫python
一、函數內部的變量名若是第一次出現,且出如今=前面,即被視爲定義一個局部變量,無論全局域中有沒有用到該變量名,函數中使用的將是局部變量,例如:編程
num = 100 def func(): num = 123 print(num) func() #輸出: 123
說明函數中定義的num是一個局部變量,會將全局變量覆蓋。再例如:app
num = 100 def func(): num += 100 print(num) func() #輸出: UnboundLocalError: local variable 'num' referenced before assignment
錯誤提示局部變量num在賦值前被應用,也就是該變量沒有定義就使用它,由此再次證實了這裏定義了一個局部變量,而不是使用的全局的num。編程語言
總結:函數內部的變量名若是第一次出現,且出如今=前面,即被視爲定義一個局部變量。ide
Python makes educated guesses on whether variables are local or global. It assumes that any variable assigned a value in a function is local.函數
From: https://www.tutorialspoint.com/python/python_functions.htmui
二、函數內部的變量名若是第一次出現,且出如今=後面,且該變量在全局域中已定義,則這裏將引用全局變量,若是該變量在全局域中沒有定義,固然會出現「變量未定義」的錯誤。例如:spa
num = 100 def func(): x = num + 100 print(x) func() #輸出: 200
表示這裏使用的num是全局變量num。htm
或者其餘使用該變量(例如調用成員函數)的狀況,也將引用全局變量,例如:
a = [1, 2] def func(): a.append(3) print(a) func() 輸出: [1, 2, 3]
總結:只要是*使用*變量,而該變量在全局域中有定義,而在局部沒有定義,則會使用全局變量。
三、函數中使用某個變量時,該變量名既有全局變量也有同名的局部變量,則會使用局部變量,例如:
num = 100 def func(): num = 200 x = num + 100 print(x) func() 結果: 300
總結:若是使用的變量在全局域中有定義,在局部域中也有定義,則默認會使用局部變量。
四、在函數中,若是想給全局變量賦值,則須要用關鍵字global生命,例如:
num = 100 def func(): global num num = 200 print(num) func() print(num) 輸出: 200 200
說明函數中給num賦值爲200是修改的全局變量,並且這裏沒有定義新的局部變量,因此後續若是再操做num也是操做的全局變量,例如:
num = 100 def func(): global num num = 200 num += 100 print(num) func() print(num) 輸出: 300 300
總結:若是要在函數中給全局變量賦值,須要用global關鍵字聲明。
========================================================
python中,對於變量做用域的規定有些不同。在諸如C/C++、java等編程語言中,默認在函數的內部是能夠直接訪問在函數外定義的全局變量的,可是這一點在python中就會有問題,下面是一個例子。
COUNT=1 def func(): COUNT = COUNT + 1 func()
Python test.py,會運行報錯:
Traceback (most recent call last):
File "test.py", line 8, in <module>
func()
File "test.py", line 6, in func
COUNT = COUNT + 1
UnboundLocalError: local variable 'COUNT' referenced before assignment
「UnboundLocalError: local variable 'COUNT' referenced before assignment」的意思是變量COUNT在賦值以前被引用。
這裏要知道python和其它編程語言不同的地方。像C/C++之類的編程語言,變量名稱其實是表明的一塊內存區域,對該變量賦值的意思就是將新的值放入該變量指定的內存區域。而對於python來講,全部的變量都是對內存區域的引用,對變量賦值至關於將變量引用的內存從一塊區域改變到另一塊存放新值的區域。也就是說,C/C++中,變量名和內存區域的對應關係不會變,變的只是對應內存中存放的值;而在python中,變量只是對存放其值的內存區域的引用,變量值的改變不是由於變量指向的內存區域中的值發生了變化,而是變量引用了新的存放新值的內存區域。python中的全部變量都是至關於java中的不可變的變量,任何一次值的改變都對應着變量引用內存區域的變化。
python中有一個id函數,python中有一個id函數,help(id)能夠看到它的說明,以下:
Help on built-in function id in module __builtin__:
id(...)
id(object) -> integer
Return the identity of an object. This is guaranteed to be unique among simultaneously existing objects.(Hint: it's the object's memory address.)
(END)
簡單地說,id函數反應的是對象的內存地址,看下面的實驗結果:
COUNT = 1 for i in range(5): COUNT = COUNT + 1 print id(COUNT)
python test.py運行結果:
11031328
11031304
11031280
11031256
11031232
這裏和上面圖上說明的相吻合,python中每一次賦值都使變量引用的內存空間發生了改變。
回到上面「referenced before assignment」的錯誤,之因此會發生這種錯誤是由於python在函數中發現對於COUNT變量的賦值,會將其添加到函數的局部命名空間(實際上,這是在函數運行到賦值操做以前發生的)。進行賦值操做時,賦值操做符的右邊引用了COUNT變量,而這時COUNT變量只是被添加到了函數的局部命名空間,而沒有被具體賦值,因此會發生上面的錯誤。實際上,這裏問題就出在賦值操做的地方,由於有賦值操做致使該變量被添加到了函數的局部命名空間。若是沒有賦值,只是引用該變量,是沒有什麼問題的,以下:
COUNT=1 def func(): temp = COUNT + 1 print "temp:",tmp print "COUNT:",COUNT func()
python test.py運行結果:
temp: 2
COUNT: 1
這樣,COUNT變量沒有被添加到函數的局部命名空間,python解釋器在函數的局部命名空間中沒有查找到它,而後,python解釋器會繼續在全局的命名空間中查找,結果在全局命名空間中找到COUNT的定義並引用它的值,因此程序運行沒有任何問題。
到這裏你可能會問,難道在函數中無法修改全局變量的值嗎?不是的,若是要在函數中修改全局變量的值,就要在函數中對該變量進行global聲明,以告訴python解釋器,該變量是全局命名空間中的。
-
# name = "gangniang" # def weihou(): # name = "chenzhuo" # def weiweihou(): # global name # 無論多深,代指最外層的全局變量 # name = "lengjing" # weiweihou() # print(name) # print(name) # weihou() # print(name) # name = "gangniang" # def weihou(): # name = "chenzhuo" # def weiweihou(): # nonlocal name # 引用外面一層的的變量 # name = "lengjing" # weiweihou() # print(name) # print(name) # weihou() # print(name)