Python 变量作用域 —— 命名空间与 LEGB 规则

时间:2023-01-16 22:47:48

一、命名空间

白话一点讲:命名空间是对变量名分组划分。

不同组的相同名称的变量视为两个独立的变量,因此隶属于不同分组(即命名空间)的变量名可以重复。

命名空间可以存在多个,使用命名空间,表示在该命名空间中查找当前名称。


二、 LEGB 原则

LEGB含义解释:
L-Local(function);函数内的名字空间
E-Enclosing function locals;外部嵌套函数的名字空间(例如closure)
G-Global(module);函数定义所在模块(文件)的名字空间
B-Builtin(Python);Python内置模块的名字空间


LEGB规定了查找一个名称的顺序为:local–>enclosing function locals–global–>builtin

In [1]: x=1

In [2]: def foo():
...: x=2
...: def inner_foo():
...: x=3
...: print('locals:',x)
...: inner_foo()
...: print('enclosing function locals:',x)
...:

In [3]: foo()
locals: 3
enclosing function locals: 2

In [4]: print('global:',x)
global: 1

稍加改动

In [5]: x=1

In [6]: def foo():
...: x=2
...: def inner_foo():
...: # x=3
...: print('locals:',x)
...: inner_foo()
...: print('enclosing function locals:',x)
...:

In [7]:

In [7]: foo()
locals: 2
enclosing function locals: 2

In [8]: print('global',x)
global 1

可以发现:当注释掉x = 3以后,函数innerfoo内部查找到的x是x = 2

在上述两个例子中,从内到外,依次形成四个命名空间:

  • def innerfoo():Local, 即函数内部命名空间;
  • def foo():Enclosing function locals;外部嵌套函数的名字空间
  • module(文件本身):Global(module);函数定义所在模块(文件)的名字空间
  • Python内置模块的名字空间:Builtin

x = 3属于函数内部命名空间,当被注释掉之后,函数innerfoo内部通过print x 使用x这个名称时,触发了名称查找动作
首先在Local命名空间查找,没有找到,然后到Enclosing function locals命名空间查找,查找成功,然后调用。


参考资料:
Python LEGB规则