一、命令空間
-
命名空間是名字和對象的映射.可以把一個namespace理解為一個字典.大部分namespace都是按Python中的字典來實現(xiàn)的.
各個命名空間是獨立的,沒有任何關系的,所以同一個命名空間中不能有重名,但不同的命名空間是可以重名而沒有任何影響.順便提一句,我稱Python 中任何一個“.”之后的命名為屬性--例如,表達式z.real 中的real 是對象z 的一個屬性.
嚴格來講,從模塊中引用命名是引用屬性:表達式modname.funcname 中, modname 是一個模塊對象,funcname 是它的一個屬性.
在這種情況下,模塊的屬性和模塊中定義的全局名稱之間會有一個簡單的映射:它們共享相同的名稱空間.
-
- 那么哪些可以是一個namespace呢?
Python的 built-in names(包括內置函數(shù),內置常量,內置類型);
一個模塊的global names(這個模塊定義的函數(shù),類,變量);
一個函數(shù)的所有l(wèi)ocal names ;
從某種意義上說,對象的屬性集也構成了一個名稱空間;
- 那么哪些可以是一個namespace呢?
- 命名空間都是有創(chuàng)建時間和生存期的.
對于Python built-in names組成的命名空間,它在Python解釋器啟動的時候被創(chuàng)建,在解釋器退出的時候才被刪除;
對于一個Python模塊的global namespace,它在這個module被import的時候創(chuàng)建,在解釋器退出的時候退出;
對于一個函數(shù)的local namespace,它在函數(shù)每次被調用的時候創(chuàng)建,函數(shù)返回或者或引發(fā)未在函數(shù)中處理的異常的時候被刪除;
- 命名空間都是有創(chuàng)建時間和生存期的.
4 查看命名空間
查看全局命名空間: globals()
查看本地命名空間: locals()
查看內建的命名空間:以Python3為例:import builtins builtins.__dict__
二、作用域
1.介紹
作用域是Python程序(文本)的某一段或某些段,在這些地方,某個命名空間中的名字可以被直接訪問。這個作用域就是這個命名空間的作用域。
直接訪問:對一個變量名的引用會在所有namespace中查找該變量,而不是通過屬性訪問.
屬性訪問:所有名字后加 . 的都認為是屬性訪問.
如 module_name.func_name ,需要指定 func_name 的名空間,屬于屬性訪問。
而 abs(-1) , abs 屬于直接訪問。
作用域 盡管范圍是靜態(tài)確定的,但它們是動態(tài)使用的。在執(zhí)行期間的任何時間,至少有三個嵌套的作用域,其命名空間可以直接訪問。
2. 四個作用域
四個作用域分別是:
Local:包含局部變量。比如一個函數(shù)/方法內部。
Enclosing:包含了非局部(non-local)也非全局(non-global)的變量.比如兩個嵌套函數(shù),內層函數(shù)可能搜索外層函數(shù)的namespace,但該namespace對內層函數(shù)而言既非局部也非全局。
Global:當前腳本的最外層。比如當前模塊的全局變量。
Built-in:Python __builtin__ 模塊(python3中改為builtins模塊).包含了內建的變量/關鍵字/函數(shù)等.
3. 著名的”LEGB-rule”,即scope的搜索順序
Local -> Enclosing -> Global -> Built-in
假設有個變量處于函數(shù)里面:當有一個變量在 local 域中找不到時,Python會找上一層的作用域,即 enclosing 域(該域不一定存在)。
enclosing 域還找不到的時候,再往上一層,搜索模塊內的 global 域
最后,會在 built-in 域中搜索。對于最終沒有搜索到時,Python會拋出一個 NameError 異常。
4. global 和 nonlocal
global 用來聲明 一個變量 是 屬于 全局作用域
nonlocal 用來 聲明 一個變量 屬于 Enclosing 作用域
代碼1:
def outer():
b = 1 # 此處 b 處于 Enclosing 作用域
def inner():
global b
b += 1 # 在 inner 函數(shù)里面想要修改 outer函數(shù) b變量的值。
print('inner_b is %d' % b)
inner()
print('outer_b is %d' % b)
outer()
# 拋出 NameError: global name 'b' is not defined
代碼2:
def outer():
b = 1
def inner():
b = b + 1 # 此時 b 變量所在的命名空間屬于 local作用域
print('inner_b is %d' % b)
inner()
print('outer_b is %d' % b)
outer()
# 拋出 UnboundLocalError: local variable 'b' referenced before assignment
代碼3:
def outer():
b = 1
def inner():
nonlocal b
b = b + 1
print('inner_b is %d' % b)
inner()
print('outer_b is %d' % b)
outer()