作用域与闭包
理解 LEGB 规则、global/nonlocal、闭包捕获与陷阱
作用域与闭包
理解变量在哪里生效,是写出干净 Python 代码的关键。
学完本章你将掌握: LEGB 规则、global/nonlocal、闭包的原理与实战。
一、LEGB 规则
Python 按 L→E→G→B 顺序查找变量:
| 层级 | 含义 | 示例 |
|---|---|---|
| L | Local(函数内部) | `def f(): x = 1` |
| E | Enclosing(外层函数) | 嵌套函数的外层 |
| G | Global(全局) | 文件顶层定义的变量 |
| B | Built-in(内置) | `print` `len` `range` |
python
x = "global"
def outer():
x = "enclosing"
def inner():
x = "local"
print(f"inner: {x}")
inner()
print(f"outer: {x}")
outer()
print(f"global: {x}")
# inner: local
# outer: enclosing
# global: global
二、global 关键字
python
counter = 0
def increment():
global counter # 声明要修改全局变量
counter += 1
increment()
print(counter) # 1
# 没有 global 的话只会创建局部变量
def broken():
# counter += 1 # ❌ UnboundLocalError!
pass
💡 尽量少用 global。大量全局变量会让代码难以调试。更好的方式是用函数返回值或类来管理状态。
三、nonlocal 关键字
修改外层(非全局)函数的变量:
python
def make_counter():
count = 0
def increment():
nonlocal count # 声明要修改外层变量
count += 1
return count
return increment
counter = make_counter()
print(counter()) # 1
print(counter()) # 2
print(counter()) # 3
四、闭包
函数 + 它创建时所在的环境 = 闭包:
python
def make_multiplier(n):
def multiply(x):
return x * n # n 来自闭包环境
return multiply
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
实战案例——配置工厂:
python
def make_tag(tag, css_class=""):
def wrap(text):
cls = f' class="{css_class}"' if css_class else ""
return f"<{tag}{cls}>{text}</{tag}>"
return wrap
h1 = make_tag("h1")
p = make_tag("p", "lead")
print(h1("标题")) # <h1>标题</h1>
print(p("段落")) # <p class="lead">段落</p>
小结
- LEGB:Local → Enclosing → Global → Built-in
global修改全局变量,nonlocal修改外层变量- 闭包 = 函数 + 创建时的环境
小练习
- 写一个
make_power(n)返回计算 x 的 n 次方的函数
💬 下一章:类与对象——面向对象编程。