Z
ZHANK
函数与模块

作用域与闭包

理解 LEGB 规则、global/nonlocal、闭包捕获与陷阱

作用域与闭包

理解变量在哪里生效,是写出干净 Python 代码的关键。

学完本章你将掌握: LEGB 规则、global/nonlocal、闭包的原理与实战。


一、LEGB 规则

Python 按 L→E→G→B 顺序查找变量:

层级含义示例
LLocal(函数内部)`def f(): x = 1`
EEnclosing(外层函数)嵌套函数的外层
GGlobal(全局)文件顶层定义的变量
BBuilt-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>

小结

  1. LEGB:Local → Enclosing → Global → Built-in
  2. global 修改全局变量,nonlocal 修改外层变量
  3. 闭包 = 函数 + 创建时的环境

小练习

  1. 写一个 make_power(n) 返回计算 x 的 n 次方的函数

💬 下一章类与对象——面向对象编程。