Python有區域性作用域和全域性作用域。還可以細分為這四種情況:
- L(local),區域性作用域
- E(enclosing),巢狀作用域
- G(global),全域性作用域
- B(built-in),內建作用域
一. L(local),區域性作用域
如果一個變數在函式內部,那麼這個變數就叫做區域性變數,函式之外是無法訪問的,例子:
def say_name():
name = 'Allen'
print(name)
say_name()
print(name)
複製程式碼
函式在執行完畢後,會將它內部的變數回收(刪除)
如果想要在函式外部使用函式內部的變數。可以使用golbal關鍵字
def say_name():
global name
name = 'Allen'
print(name)
say_name()
print(name)
複製程式碼
二. E(enclosing),巢狀作用域
作用域之間是可以相互巢狀的,比如兩個函式之間巢狀。裡面的函式可以訪問它外部函式作用域中的變數,但是外面的函式無法訪問內部函式的作用域,例子:
def foo():
a = 1
def bar():
b = 2
print(a)
bar()
print(b)
foo()
複製程式碼
但是,如果在內部函式中直接重新賦值外部函式作用域中的變數,外部函式作用域中的變數是不會改變的,會得到一個新的區域性變數。同樣的在函式中改變全域性作用域的變數,也是這樣。
b = 1
def foo():
a = 1
def bar():
a = 2
print('bar:', a)
def fn():
b = 2
print('fn', b)
bar()
fn()
print('foo:', a)
foo()
print('golbal:', b)
複製程式碼
如果想要修改原值,那麼就要用到nonlocal關鍵字,例子:
注意,nonlocal關鍵字只針對區域性變數,如果尋找的變數處於全域性作用域中,會報錯,,例子:
a = 1
def foo():
nonlocal a
a = 2
print('foo:', a)
foo()
複製程式碼
如果nonloacl關鍵字在上一層中找到了變數,那麼就會停止尋找,如果沒有就繼續向上直到全域性作用域:
def foo():
a = 1
def bar():
print('bar:', a)
def fn():
nonlocal a
a = 2
print('fn:', a)
fn()
bar()
print('foo:', a)
foo()
複製程式碼
三. G(global),全域性作用域
全域性作用域就是模組最頂層宣告的變數。每一個.py結尾的檔案就是一個模組,每個模組都有不同的全域性作用域,當一個模組匯入另一個模組後,在當前模組就可以訪問另一個模組的全域性作用域中的變數了。全域性作用域中的變數,在當前模組的任何地方都可以訪問到。
# b.py
module_name = 'b'
# a.py
import b
print(b.module_name)
複製程式碼
四. B(built-in),內建作用域
內建作用域就是Python中內建模組中的變數,比如我們可以直接使用print方法而不用匯入任何模組。
Python中尋找變數的規則會按照LEGB規則尋找:
Local -> Enclosing -> Global -> Built-in
最後說一點的是,Python中沒有塊級作用域,也就是在類似for語句中定義的變數就是全域性作用域中的變數: