17370845950

Python闭包原理解析_状态保持机制说明【教程】
Python闭包指内层函数记住并引用外层函数的局部变量,即使外层函数已结束,变量仍驻留内存;需满足嵌套定义、引用外层局部变量、外层返回内层函数对象三条件。

Python闭包的核心在于:**内层函数记住了它被定义时所在作用域的变量,即使外层函数已经执行完毕,这些变量仍被保留在内存中供内层函数使用**。这不是简单的值拷贝,而是对变量对象的引用保持。

什么是闭包?三个必要条件

一个函数要构成闭包,必须同时满足:

  • 存在嵌套函数(内层函数定义在外层函数内部)
  • 内层函数引用了外层函数的局部变量(非全局、非参数传入)
  • 外层函数返回了内层函数(不是调用结果,而是函数对象本身)

闭包如何保存状态?——freevars__closure__

当满足闭包条件后,Python会自动为内层函数创建__closure__属性,它是一个元组,每个元素是cell对象,封装了被引用的外层变量。可通过func.__code__.co_freevars查看变量名。

例如:

def make_adder(n):
    def add(x):
        return x + n  # 引用了外层n
    return add

plus3 = make_adder(3) print(plus3.closure) # (,) print(plus3.code.co_freevars) # ('n',) print(plus3.closure[0].cell_contents) # 3

闭包 vs 普通嵌套:关键区别在变量生命周期

普通嵌套函数调用结束后,其局部变量随栈帧销毁;而闭包中的外层变量因被内层函数“捕获”,会延长生命周期,直到所有引用它的闭包函数对象被回收。

注意:闭包捕获的是变量的引用,不是快照。如果外层变量可变(如列表),后续修改会影响所有共享该闭包的函数:

def make_counter():
    count = [0]  # 用列表避免重新赋值
    def inc():
        count[0] += 1
        return count[0]
    return inc

c1 = make_counter() print(c1()) # 1 print(c1()) # 2

常见陷阱:循环中创建多个闭包

在for循环中直接创建闭包,容易误以为每次捕获的是当前i值,实际捕获的是同一个变量i的最终值:

# ❌ 错误写法
funcs = []
for i in range(3):
    funcs.append(lambda: i)  # 全部返回2

✅ 正确写法:用默认参数固化当前值

funcs = [] for i in range(3): funcs.append(lambda x=i: x)

或用闭包函数封装

def make_func(x): return lambda: x funcs = [make_func(i) for i in range(3)]