)
闭包是指在一个嵌套函数中内部函数引用了外部函数的变量并且外部函数返回了内部函数。闭包会“记住”外部函数的变量即使外部函数已经执行完毕。一、什么是闭包1. 基本结构def outer(x): def inner(y): return x y return inner # 创建闭包 add_5 outer(5) result add_5(3) print(result) # 8关键要素存在嵌套函数inner内部函数引用了外部函数的变量x外部函数返回了内部函数2. 闭包的本质def outer(x): def inner(y): return x y return inner add_5 outer(5) add_10 outer(10) print(add_5(3)) # 8 print(add_10(3)) # 13 # 查看闭包捕获的变量 print(add_5.__closure__) # (cell at 0x...: int object at 0x...,) print(add_5.__closure__[0].cell_contents) # 5二、闭包的特点1. 记住外部变量的值def counter(): count 0 def increment(): nonlocal count count 1 return count return increment c1 counter() c2 counter() print(c1()) # 1 print(c1()) # 2 print(c1()) # 3 print(c2()) # 1独立的闭包有自己的 count2. 延迟计算def make_power(exponent): def power(base): return base ** exponent return power square make_power(2) # 平方函数 cube make_power(3) # 立方函数 print(square(5)) # 25 print(cube(5)) # 125三、闭包的实现原理1.__closure__属性每个闭包函数都有一个__closure__属性存储捕获的外部变量。def outer(x, y): z 100 def inner(): return x y z return inner func outer(10, 20) # 查看闭包捕获的变量 print(func.__closure__) # (cell at 0x...: int object at 0x..., # cell at 0x...: int object at 0x..., # cell at 0x...: int object at 0x...) # 查看捕获的值 for cell in func.__closure__: print(cell.cell_contents) # 10, 20, 1002.__code__.co_freevars自由变量def outer(x): def inner(y): return x y return inner func outer(10) print(func.__code__.co_freevars) # (x,) print(func.__code__.co_varnames) # (y,)四、闭包 vs 类闭包在某些场景可以作为轻量级的替代方案。# 使用闭包实现计数器 def counter_closure(): count 0 def increment(): nonlocal count count 1 return count return increment # 使用类实现计数器 class CounterClass: def __init__(self): self.count 0 def increment(self): self.count 1 return self.count # 闭包更简洁 c1 counter_closure() print(c1()) # 1 # 类更明确 c2 CounterClass() print(c2.increment()) # 1特性闭包类代码量少多可读性简单场景好复杂场景好状态通过nonlocal修改通过self修改方法数量单个函数可以有多个方法适用场景简单状态保存复杂业务逻辑五、调试闭包def outer(x, y): z 100 def inner(w): return x y z w return inner func outer(10, 20) # 1. 查看闭包中捕获的变量名 print(func.__code__.co_freevars) # (x, y, z) # 2. 查看闭包中捕获的值 for cell in func.__closure__: print(cell.cell_contents) # 10, 20, 100 # 3. 查看函数的局部变量名 print(func.__code__.co_varnames) # (w,)六、其他特性说明定义函数捕获的外部变量条件嵌套函数 引用外部变量 返回内部函数捕获方式按引用捕获不是按值内存外部变量不会随函数结束而销毁访问读直接访问写需要nonlocal常见应用装饰器、计数器、缓存核心闭包会记住外部函数的变量每次调用外部函数都会创建新的闭包实例修改外部变量需要nonlocal关键字闭包是装饰器的底层实现原理