Python命名空间与变量作用域:理解名称、绑定与作用域
Python命名空间与变量作用域
通过清晰示例和最佳实践,探索Python中名称、命名空间和变量作用域的工作原理。
Python中的名称是什么?
在“The Zen of Python”(import this)最后一行写道:“命名空间是个绝妙主意——让我们多用那些!”那么什么是命名空间?先定义名称。
名称或标识符是引用对象的标签。Python中一切皆对象,名称提供便捷访问方式。
例如执行 a = 2 时,整数 2 存入内存,a 成为其引用。内置 id() 返回对象内存地址。
# 注意:你的id值可能不同
a = 2
print('id(2) =', id(2))
print('id(a) =', id(a))
输出
id(2) = 9302208 id(a) = 9302208
两名字指向同一对象,id() 值匹配。看重新绑定 a 会怎样:
# 注意:你的id值可能不同
a = 2
print('id(a) =', id(a))
a = a + 1
print('id(a) =', id(a))
print('id(3) =', id(3))
b = 2
print('id(b) =', id(b))
print('id(2) =', id(2))
输出
id(a) = 9302208 id(a) = 9302240 id(3) = 9302240 id(b) = 9302208 id(2) = 9302208
执行 a = a + 1 时,创建新对象 3,a 现在引用它。注意 id(a) 和 id(3) 相同。后续 b = 2 仅将 b 绑定到现有 2 对象,避免重复存储。

这种动态名称绑定使Python灵活:单一标识符可指向任意类型值——包括函数。
def printHello():
print("Hello")
a = printHello
a()
输出
Hello
标识符 a 现引用函数 printHello,可直接调用。
什么是命名空间?
命名空间是从名称到对象的映射。可视为保存你定义的每个标识符及其关联对象的字典。
Python同时支持多个相互隔离的命名空间。解释器创建包含所有内置名称的全局命名空间,持续整个会话。每个模块有自己的全局命名空间,每个函数或类定义引入新的局部命名空间。

Python变量作用域
命名空间存在的同时,作用域决定无需限定即可访问名称的区域。
任意时刻,程序至少有三层嵌套作用域:
- 当前执行函数的局部作用域。
- 模块的全局作用域。
- 始终可用的内置作用域。
函数内引用名称时,Python先搜索局部命名空间,再全局,最后内置。若函数包含另一函数,内层引入新的嵌套作用域。
示例:作用域与命名空间交互
考虑代码:
def outer_function():
b = 20
def inner_func():
c = 30
a = 10
此处 a 位于模块全局命名空间。b 局部于 outer_function,c 属于 inner_func 的嵌套局部命名空间。
在 inner_func 内,c 是局部,b 是非局部,a 是全局。可读写 c,但只能读 b 和 a,除非用 global 或 nonlocal 显式声明。
更具体演示:
def outer_function():
a = 20
def inner_function():
a = 30
print('a =', a)
inner_function()
print('a =', a)
a = 10
outer_function()
print('a =', a)
输出演示三个不同的 a 绑定:
a = 30 a = 20 a = 10
强制所有赋值指向全局 a,用 global 关键字:
def outer_function():
global a
a = 20
def inner_function():
global a
a = 30
print('a =', a)
inner_function()
print('a =', a)
a = 10
outer_function()
print('a =', a)
输出现反映单一全局 a:
a = 30 a = 30 a = 30
这些示例阐释Python的命名空间和作用域规则如何管辖变量可见性和变更。
Python