一.名稱空間
1.認識名稱空間
我們都知道,變量在內存中存儲的方式如下:
所有的名稱(變量名、函數名等)都放在棧區,那麼就會存在一個問題,就是名稱重複,假設有一個名爲a的函數,同時也存在一個名爲a的變量,這樣的話肯定有一個失效,被另一個覆蓋。爲了解決這個問題,python將棧區空間劃分爲3部分,即內置名稱空間、全局名稱空間、局部名稱空間。如下圖:
所以名稱空間就是存放名字的地方的代稱,不是真是存在的東西,只是對棧區的一個劃分。
2.三種名稱空間詳解
1.內置名稱空間
內置名稱空間: 存放python解釋器自帶的名稱,比如print函數,我們自己又沒有定義,但是能直接用
存活週期: python解釋器啓動則產生,python解釋器關閉則銷燬
內置名稱空間只有一個
type(print)
結果如下:
2.局部名稱空間
局部名稱空間: 存放函數體代碼中的名稱
存活週期: 函數調用時創建,函數執行完畢則銷燬
局部名稱空間可以有多個,不管是不是同一個函數,調用一次創建一個局部名稱空間。
3.全局名稱空間
全局名稱空間: 存放除內置和局部名稱空間外所有名稱
存活週期:python程序執行時創建,python程序執行完畢則銷燬
全局名稱空間只有一個
總結:
名稱空間 | 存放名稱 | 存貨週期 | 個數 |
---|---|---|---|
內置名稱空間 | python解釋器自帶的名稱 | python解釋器啓動產生,python解釋器關閉銷燬 | 1個 |
全局名稱空間 | 除內置和局部名稱空間外其他所有名稱 | python程序執行創建,python程序執行完畢銷燬 | 1個 |
局部名稱空間 | 函數體代碼中的名稱 | 函數調用創建,調用完畢銷燬 | 多個 |
3.名稱空間的加載順序
4.名稱查找順序
大致順序:
詳細順序:
先從當前所在的名稱空間找,找不到按照大致順序去別的名稱空間找。
eg:在全局代碼中調用變量x,如果沒有就去內置名稱空間找,不會去局部。
實例代碼1:
def func():
print(format) #先在局部名稱空間找format,沒找到後去全局名稱空間找,沒找到後去內置名稱空間找
func()
結果如下:
實例代碼2:
def f1():
print(x)
x = 1
f1() 結果爲:1
二.作用域
1.認識作用域
作用域:名稱作用有效區域,
將三個名稱空間內名稱的作用區域劃分爲全局作用域和局部作用域。
全局作用域: 內置名稱和全局名稱的作用範圍,全局有效
局部作用域:局部名稱的作用範圍,局部有效
2.globals、locals、global、nonlocal
1.globals與locals
globals():查看全局作用域中的所有名稱
locals():查看當前作用域中的所用名稱,在全局作用域中使用locals結果與globals相同
二者的返回值都是字典
def func1():
pass
print(globals)
結果如下:
def func():
x = 2
print(locals)
結果如下:
2.global、nonlocal
global:聲明是全局作用域中的名稱,如果不存在則創建
nonlocal:聲明是局部作用域的名稱,會調用離自己最近的局部作用域中的名稱,如果沒有再上一層,若局部作用域中找不到則報錯
示例代碼1:
def a():
class A:
pass
a()
print(A) 結果爲:<class '__main__.A'>
示例代碼2:
def a():
a = 1
def b():
def c():
nonlocal a
print(a)
c()
b()
a() 結果爲:1
示例代碼3:
a = 1
def a():
def b():
def c():
nonlocal a
print(a)
c()
b()
a() 結果爲:報錯,因爲局部作用域中不存在a
三.注意
切記:涉及名稱空間的嵌套時,記住函數內調用的名稱是在函數定義時就已經確定了,與調用位置無關。
eg:
x = 2
def func():
x = 1
def inner():
print(x)
return inner
func()() 結果爲1
四.小練習
input = 333
def func():
input = 444
func()
print(input)
def func():
print(x)
x = 111
func()
def func():
print(x)
def foo():
x = 222
func()
x = 333
foo()
x = 111
def func():
print(type(x))
x = 222
func()
input = 111
def f1():
def f2():
input = 333
print(input)
input = 222
f2()
input = 333
f1()
x = 111
def foo():
print(x)
def bar():
print(x)
foo()
bar()
x = 1
def func2():
func1()
x = 2
def func1():
print(x)
x = 3
func2()