本文目录导读:
我将通过几个循序渐进的Python案例来帮助你理解闭包的概念。
什么是闭包(基础案例)
def outer_function(msg):
message = msg
def inner_function():
print(message) # 访问外部函数的变量
return inner_function # 返回内部函数
# 创建闭包
hello_func = outer_function("Hello, World!")
bye_func = outer_function("Goodbye!")
# 调用闭包
hello_func() # 输出: Hello, World!
bye_func() # 输出: Goodbye!
print(hello_func.__closure__) # 查看闭包信息
print(hello_func.__closure__[0].cell_contents) # 输出: Hello, World!
计数器 - 保留状态的闭包
def make_counter():
count = 0 # 外部函数的局部变量
def counter():
nonlocal count # 声明count是外部变量
count += 1
return count
return counter
# 创建两个独立的计数器
counter1 = make_counter()
counter2 = make_counter()
print("计数器1:")
print(counter1()) # 1
print(counter1()) # 2
print(counter1()) # 3
print("计数器2:")
print(counter2()) # 1 (独立于counter1的状态)
print(counter2()) # 2
# 闭包保留了count的值
print(f"counter1的闭包值: {counter1.__closure__[0].cell_contents}") # 3
延迟计算 - 闭包保存参数
def power_function(exponent):
def power(base):
return base ** exponent
return power
# 创建不同的幂函数
square = power_function(2)
cube = power_function(3)
# 闭包记住了不同的exponent
print(f"5的平方: {square(5)}") # 25
print(f"5的立方: {cube(5)}") # 125
# 延迟计算示例
print(f"延迟计算: {square(3)}") # 9 (传入base才计算)
装饰器模式 - 闭包的经典应用
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 执行时间: {end_time - start_time:.4f}秒")
return result
return wrapper
# 使用装饰器(本质是闭包)
@timer_decorator
def slow_function():
total = sum(range(1000000))
return total
# 等价于: slow_function = timer_decorator(slow_function)
result = slow_function()
print(f"结果: {result}")
工厂函数 - 创建特定功能的函数
def make_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
# 创建不同倍数的乘法器
double = make_multiplier(2)
triple = make_multiplier(3)
ten_times = make_multiplier(10)
# 每个闭包都保留了自己的factor
print(f"5的双倍: {double(5)}") # 10
print(f"5的三倍: {triple(5)}") # 15
print(f"5的十倍: {ten_times(5)}") # 50
闭包与lambda函数
# 闭包 vs lambda
def make_multipliers():
multipliers = []
for i in range(1, 4):
# 使用默认参数捕获当前i的值
multipliers.append(lambda x, multiplier=i: x * multiplier)
return multipliers
# 错误示例(常见的陷阱)
def make_multipliers_bad():
multipliers = []
for i in range(1, 4):
multipliers.append(lambda x: x * i) # i在调用时才查找
return multipliers
# 正确使用闭包
multipliers = make_multipliers()
print("正确闭包:")
for i, mult in enumerate(multipliers, 1):
print(f"5 * {i} = {mult(5)}")
# 错误的闭包(所有函数都使用相同的i)
multipliers_bad = make_multipliers_bad()
print("\n错误闭包:")
for i, mult in enumerate(multipliers_bad, 1):
print(f"5 * {i} = {mult(5)}") # 所有结果都是15
实际应用:缓存函数
def make_cache():
cache = {} # 外部变量保存缓存
def cached_function(key, value=None):
if key in cache:
print(f"缓存命中: {key}")
return cache[key]
else:
if value is not None:
cache[key] = value
print(f"添加缓存: {key}")
return value
else:
print(f"键不存在: {key}")
return None
return cached_function
# 使用缓存
my_cache = make_cache()
my_cache("user1", {"name": "Alice", "age": 25})
my_cache("user2", {"name": "Bob", "age": 30})
print(my_cache("user1")) # 缓存命中
print(my_cache("user3")) # 键不存在
# 查看缓存状态
print(f"\n缓存内容: {my_cache.__closure__[0].cell_contents}")
闭包的调试和检查
def analyze_closure(func):
"""分析闭包的内部结构"""
if hasattr(func, '__closure__') and func.__closure__:
print(f"函数名: {func.__name__}")
print(f"自由变量数量: {len(func.__closure__)}")
for i, cell in enumerate(func.__closure__):
print(f" 变量{i}: {func.__code__.co_freevars[i]} = {cell.cell_contents}")
else:
print("这不是闭包或没有自由变量")
# 测试
def test_closure():
x = 10
y = 20
def inner():
return x + y
return inner
closure_fn = test_closure()
analyze_closure(closure_fn)
# 输出:
# 函数名: inner
# 自由变量数量: 2
# 变量0: x = 10
# 变量1: y = 20
- 闭包 = 函数 + 环境:内部函数 + 外部函数的变量环境
- 状态保持:闭包可以记住创建时的环境
- 独立性:每次调用外部函数都会创建独立的闭包
- 数据隐藏:外部变量不会被外部直接访问
通过这些案例,你可以看到闭包在实际编程中的强大功能:状态管理、延迟计算、工厂模式、装饰器等,理解闭包对于掌握Python的高级特性非常重要。