Python命名空間

命名空間namespace

定義
我對於命名空間的理解是,由變量名到對象的一個映射,相當於字典中的key對應一個values。所以在同一個環境中,不能有相同的key,但在不同的環境中,key的值是可以重複的。
namespace又可以分爲三類:

  • 內建命名空間(Builtins):在啓動python解釋器時創建,我覺得是特殊的全局命名空間,因爲它相當於導入了builtins模塊
  • 全局命名空間(Global):在導入模塊時創建
  • 局部命名空間(Local):在調用函數時創建
  • 內嵌函數命名空間(Enclosing):函數內嵌函數時的特殊局部命名空間

創建
由以上的定義可以知道,在執行一個py腳本的時候,命名空間的創建流程是:內建->全局->局部(前提是內部有函數的調用)

Python 3.7.0 (default, Jun 28 2018, 07:39:16) 
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def func1():
...     name = 1
...     print('localspace:',locals())
...     print('globalspace:',globals())
...     def func2():
...             print('before func1 local:',locals())
...             print('before func1 global:',globals())
...             ayu = name
...             print('after func1 local:',locals()) #1
...             print('after func1 global:',globals())
...     func2() #2
...     print('after func2 local:',locals())
...     print('after func2 global:',globals())
... 
>>> func1()
localspace: {'name': 1}
globalspace: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'func1': <function func1 at 0x10384c598>}
before func1 local: {'name': 1}
before func1 global: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'func1': <function func1 at 0x10384c598>}
after func1 local: {'name': 1, 'ayu': 1}
after func1 global: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'func1': <function func1 at 0x10384c598>}
after func2 local: {'name': 1, 'func2': <function func1.<locals>.func2 at 0x103855378>}
after func2 global: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'func1': <function func1 at 0x10384c598>}
>>> del(func1) #3
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
>>> 

以上代碼在命令行中執行,#2中調用完func2之後,#1中的局部命名空間被刪除,執行#3之後,func1中的全局命名空間被刪除,而builtins命名空間需要在退出解釋器後纔會被回收
所以命名空間回收的順序是局部->全局->builtins

調用
在調用變量是,遵循LEGB的順序,即Local->Enclosing(前提是有內嵌函數)->Global->Builtins

>>> def func1():
...     x = 1
...     print(x)
...     def func2():
...             x += x
...             print(x)
...     func2()
... 
>>> func1()
1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in func1
  File "<stdin>", line 5, in func2
UnboundLocalError: local variable 'x' referenced before assignment
>>> 

在執行func2時會報錯,因爲執行func2時,會在局部變量中創建x,然後從其局部變量中查找x,始終沒有到Enclosing中取。

參考的博客
> 由一個例子到python的名字空間
>詳解python命名空間和作用域

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章