前言
命名空間通俗的理解就是對象或變量的作用范圍,在python中分為局部命令空間、模塊命名空間和build-in全局命名空間。
局部命名空間
局部命名空間即在一個函數或一個類中起作用的變量或引用的字典集合,使用local()即可獲得局部的命名空間,是一個字典。
class Person(object):
name = 'cai'
print(locals()) # {'__module__': '__main__', '__qualname__': 'Person', 'name': 'cai'}
locals()['age'] = 20
print(locals()) # {'__module__': '__main__', '__qualname__': 'Person', 'name': 'cai', 'age': 20}
def get_name(self):
print(locals()) # {'self': <__main__.Person object at 0x0000026BF6E35358>}
print(locals()) # {'__module__': '__main__', '__qualname__': 'Person', 'name': 'cai', 'age': 20, 'get_name': <function Person.get_name at 0x0000026BF6B74598>}
if __name__ == "__main__":
Person().get_name()
-
所有在類或函數中定義或引用的對象會被收集到該類或函數的局部命名空間中;
-
local()方法會獲取當前所處位置的局部命名空間,可以手動往局部命名空間中添加鍵值對;
-
python作為解釋型語言,代碼上下文從上往下加載,其實就是不斷往命名空間中添加對象的鍵值對;
模塊命名空間
模塊命名空間即在當前模塊中的所有的對象的字典集合,使用globals()獲取模塊命名空間。
from test import name
import os
class Person(object):
pass
if __name__ == "__main__":
print(globals())
print(locals())
-
如果是在模塊中直接使用globals()和locals()獲取命名空間,它們得到的結果是一模一樣的;
-
模塊命名空間收集了所有隱藏屬性、定義的對象或導入的模塊或對象的字典集合;
-
從某個模塊中導入一個對象,本質就是將該對象的鍵值對加入到模塊的命名空間中,同理直接導入某個模塊,就是將整個模塊的命名空間導入到另一個模塊。
全局命名空間
除了局部命名空間和模塊命名空間外,還有一種就是全局命名空間了,全局命名空間中的對象在任何模塊無需導入就可以直接使用,其本質上是python的builtins模塊的命名空間。
l = list()
d = dict()
如list、dict等方法無需導入即可使用,原因是每個py模塊有一個隱藏的屬性_builtins_,該屬性指向全局的命名空間所在的模塊,相當於每次都自動加載了builtins模塊的命名空間。
修改命名空間
程序的運行邏輯一般在方法或函數中,它們默認使用的局部命名空間,如果想要在函數中修改模塊命名空間就需要將模塊命名空間引入到局部命名空間中。
name = 'xiao'
def get():
x = 1
def name():
global name
nonlocal x
print(locals()) # {'x': 1}
x = 2
print(locals()) # {'x': 2}
name = 'cao'
return name
if __name__ == "__main__":
get()()
print(globals()) # {....,'name': 'cao', 'get': <function get at 0x0000029E49AB2EA0>}
-
通過global關鍵字可以將模塊的命名空間中的變量引入到局部命名空間;nonlocal可以在閉包中將外層函數的命名空間引入到內層。
-
注意nonlocal關鍵字是不能在方法中將類的屬性等引入到方法中進行修改的。
總結
-
全局命名空間在所有模塊中可用,python自動加載,無需導入;
-
模塊命名空間收集本模塊所有的對象的鍵值對,所有模塊層面代碼執行時會從模塊命名空間查找對象;
-
所有函數或方法中變量都只存在於局部命名空間,這使得各函數變量相互隔離。