首页 / Python3 入门教程 / 变量作用域与闭包

Python3 入门教程

变量作用域与闭包

本教程共 70 篇 · 第 24 篇 · 更新于 2026-07-22 · 约 3 分钟阅读

PythonPython3 入门教程作用域LEGB闭包nonlocal

24. 变量作用域与闭包

本节目标:理解 LEGB 规则,掌握 global 和 nonlocal,学会使用闭包。

LEGB 规则

Python 查找变量时,按这个顺序:

  1. Local:函数内部
  2. Enclosing:外层嵌套函数
  3. Global:模块全局
  4. Built-in:内置作用域
x = "global"

def outer():
    x = "enclosing"

    def inner():
        x = "local"
        print(x)   # local,L 层找到

    inner()

outer()

如果 inner 里没有 x = "local",会去找 outer 里的 x;outer 里也没有,去找 global;再没有,找内置。

global 关键字

想在函数内部修改全局变量,用 global 声明:

count = 0

def increment():
    global count
    count += 1

increment()
increment()
print(count)   # 2
Warning

如果不加 global,Python 会把 count += 1 里的 count 当作局部变量,但赋值前引用了它,会报 UnboundLocalError

count = 0

def broken():
    count += 1   # UnboundLocalError!

nonlocal 关键字

nonlocal 用于修改外层(非全局)函数的变量:

def outer():
    x = 10

    def inner():
        nonlocal x
        x = 20
        print(f"inner: {x}")

    inner()
    print(f"outer: {x}")

outer()
# inner: 20
# outer: 20
Note

nonlocalglobal 的区别:global 跳到模块顶层,nonlocal 只跳到最近的外层函数。

闭包(Closure)

闭包是指「引用了外部函数变量的内部函数」。即使外部函数已经执行完毕,闭包仍然能访问那些变量。

def make_multiplier(n):
    def multiplier(x):
        return x * n
    return multiplier

times3 = make_multiplier(3)
times5 = make_multiplier(5)

print(times3(10))   # 30
print(times5(10))   # 50

make_multiplier 执行完后,它的局部变量 n 本应该被销毁。但因为返回的 multiplier 还在引用 n,所以 n 被「封闭」在闭包里,继续存活。

Tip

闭包的价值在于「数据封装」。不用类,也能实现带状态的功能。

闭包的陷阱:延迟绑定

在循环里创建闭包,容易踩坑:

def make_functions():
    funcs = []
    for i in range(3):
        def func():
            return i
        funcs.append(func)
    return funcs

f1, f2, f3 = make_functions()
print(f1(), f2(), f3())   # 2 2 2,不是 0 1 2

三个闭包都引用了同一个 i,而循环结束时 i 的值是 2。

解决办法:让闭包在定义时就捕获当前值。

def make_functions():
    funcs = []
    for i in range(3):
        def func(x=i):   # 默认参数在定义时求值
            return x
        funcs.append(func)
    return funcs

f1, f2, f3 = make_functions()
print(f1(), f2(), f3())   # 0 1 2

或者用 functools.partial

from functools import partial

def make_functions():
    funcs = []
    for i in range(3):
        funcs.append(partial(lambda x: x, i))
    return funcs

什么时候用闭包

闭包适合简单的状态保持场景。如果状态和行为越来越复杂,就该用类了。

# 用闭包实现简单的计数器
def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

c = make_counter()
print(c())   # 1
print(c())   # 2
print(c())   # 3

来源:参考了 runoob「Python3 命名空间作用域」、liaoxuefeng「函数式编程」等,改写后所得。