namespace
C 中,变量名是内存地址的别名,
而在 Python 中,名字是一个字符串对象,它与它指向的对象构成一个{name:object}关联。
也可以把一个namespace理解为一个字典。
作用域
Python 中name-object的关联存储在不同的作用域中,各个不同的作用域是相互独立的。
而我们就在不同的作用域中搜索name-object。
Python中使用变量名引用对象,需要使用该变量时,就在命名空间中进行搜索,获取对应的对象。
直接访问一个变量,会在四个namespace中查找:
- locals 是函数内的名字空间,包括局部变量和形参
- enclosing 外部嵌套函数的名字空间(闭包中常见)
- globals 全局变量,函数定义所在模块的名字空间
- builtins 内置模块的名字空间
当程序引用某个变量的名字时,就会从当前名字空间开始查找,查找顺序(LEGB):
locals -> enclosing function -> globals -> __builtins__
生命周期
1.__builtins__ 在python解释器启动的时候,便已经创建,直到退出。
2.globals 在模块定义被读入时创建,通常也一直保存到解释器退出。
3.locals 在函数调用时创建,直到函数返回,或者抛出异常之后,销毁。
另外递归函数每一次均有自己的名字空间。
print('1. globals: ', globals())
a = 1000000000
def func():
print('1. func locals: ', locals())
a = 1
b = 2
global p # 函数内部调用global声明的时候,可将变量存储在globals中
p = 9999
def inner_func():
print('1. inner_func locals: ', locals())
m = 3
n = 4
nonlocal a # nonlocal关键字来修改外部嵌套函数的名字空间。只能在内部嵌套函数使用。
a = m + n
print(a)
print('2. inner_func locals: ', locals())
inner_func()
print(a, b, p)
print('2. func locals: ', locals())
func()
print(a)
print('2. globals: ', globals())
1. globals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x109457278>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'test.py', '__cached__': None}
1. func locals: {}
1. inner_func locals: {'a': 1}
7
2. inner_func locals: {'a': 7, 'm': 3, 'n': 4}
7 2 9999
2. func locals: {'b': 2, 'inner_func': <function func.<locals>.inner_func at 0x10949e2f0>, 'a': 7}
1000000000
2. globals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x109457278>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'test.py', '__cached__': None, 'a': 1000000000, 'func': <function func at 0x108fb21e0>, 'p': 9999}