Python3 命名空间/作用域
命名空间的种类、作用域查找规则 LEGB、global 与 nonlocal 的使用。
命名空间
A namespace maps names to objects. Python has three: built-in (builtins, alive from interpreter start), global (module level), and local (created per function call, destroyed on return).
import builtins
g = "global"
def f():
l = "local"
print(l, g)
print('len' in dir(builtins))
f()
print('g' in globals(), 'l' in globals())
print(hasattr(builtins, 'len'), hasattr(builtins, 'g'))local global
True
True False
True False作用域
Scope is the region where a namespace is visible; lookup is LEGB: Local → Enclosing → Global → Built-in. The key rule: any assignment inside a function makes that name local for the whole function.
x = "global"
def outer():
x = "enclosing"
def inner():
print("inner sees:", x)
inner()
outer()
def shadow():
print(x)
x = "local"
try:
shadow()
except UnboundLocalError as e:
print("UnboundLocalError:", e)
def use_global():
global x
x = "changed"
use_global()
print(x)inner sees: enclosing
UnboundLocalError: cannot access local variable 'x' where it is not associated with a value
changedUnboundLocalError is the classic scope trap: once you assign to x anywhere in the function, Python treats it as local — so the earlier print(x) hits an unbound name.global 与 nonlocal
global declares a module-level name; nonlocal declares one from an enclosing function (not global). Both must appear inside the function and before the name is used.
count = 0
def inc():
global count
count += 1
inc(); inc()
print(count)
def make_counter():
n = 0
def step():
nonlocal n
n += 1
return n
return step
c = make_counter()
print(c(), c(), c())2
1 2 3global sparingly — it creates hidden coupling and hurts testability. Prefer keeping state in a class or a mutable container, or pass values through returns.命名空间
命名空间是「名字到对象」的映射。Python 有三种:内置命名空间(builtins,解释器启动即存在)、全局命名空间(模块级)、局部命名空间(函数调用时创建,返回时销毁)。
import builtins
g = "global"
def f():
l = "local"
print(l, g)
print('len' in dir(builtins))
f()
print('g' in globals(), 'l' in globals())
print(hasattr(builtins, 'len'), hasattr(builtins, 'g'))local global
True
True False
True False作用域
作用域是命名空间可见的代码范围,查找顺序是 LEGB:Local → Enclosing → Global → Built-in。关键规则:函数体内只要有赋值语句,该名字在整个函数内都算局部变量。
x = "global"
def outer():
x = "enclosing"
def inner():
print("inner sees:", x)
inner()
outer()
def shadow():
print(x)
x = "local"
try:
shadow()
except UnboundLocalError as e:
print("UnboundLocalError:", e)
def use_global():
global x
x = "changed"
use_global()
print(x)inner sees: enclosing
UnboundLocalError: cannot access local variable 'x' where it is not associated with a value
changedUnboundLocalError 是最常见的作用域坑:print(x) 之后又给 x 赋值,Python 就认为 x 是局部的,于是打印时它还没被绑定。global 与 nonlocal
global 声明名字来自模块级,nonlocal 声明名字来自外层函数(不含全局)。二者都必须在函数内、且在该名字被使用之前声明。
count = 0
def inc():
global count
count += 1
inc(); inc()
print(count)
def make_counter():
n = 0
def step():
nonlocal n
n += 1
return n
return step
c = make_counter()
print(c(), c(), c())2
1 2 3global:它会制造隐式耦合,让函数难以测试。更常见的做法是把状态放在类或可变容器里,或者用返回值传递。