文章目录
闭包是Python中一个强大且有用的概念,它指的是一个函数能够记住并访问其词法作用域(lexical scope)中的变量,即使该函数在其作用域之外执行。
闭包的基本概念
闭包需要满足三个条件:
1、必须有一个嵌套函数(函数内部定义函数)
2、嵌套函数必须引用外部函数中的变量
3、外部函数必须返回嵌套函数
代码示例:
def outer_function(msg):
# 外部函数的变量
message = msg
def inner_function():
# 内部函数访问外部函数的变量
print(message)
# 返回内部函数(不执行)
return inner_function
# 直接调用
outer_function("Hello, Closure!")()
# 创建闭包
my_func = outer_function("Hello, Closure!")
my_func() # 输出: Hello, Closure!
闭包的特点
1、记住状态:闭包可以记住创建时的环境状态
2、数据封装:可以用于隐藏数据,实现类似面向对象的私有变量
3、延迟执行:可以在需要时才执行内部函数
实际应用示例
计数器实现:
def counter():
count = 0
def increment():
nonlocal count # 声明count不是局部变量
count += 1
return count
return increment
# 创建计数器
counter1 = counter()
print(counter1()) # 1
print(counter1()) # 2
print(counter1()) # 3
# 另一个独立的计数器
counter2 = counter()
print(counter2()) # 1
输出显示:
1
2
3
1
函数工厂:
def power_factory(exponent):
def power(base):
return base ** exponent
return power
square = power_factory(2)
cube = power_factory(3)
print(square(5)) # 25
print(cube(5)) # 125
注意事项
1、变量绑定:闭包中引用的变量是在运行时才查找的,不是定义时的值
def create_multipliers():
return [lambda x: i * x for i in range(5)]
for multiplier in create_multipliers():
print(multiplier(2)) # 全部输出8,因为i最后是4
问题原因:
1、这里所有的 lambda 函数都共享同一个变量 i
2、当这些函数被调用时,它们查找的是 i 的当前值(不是创建时的值)
3、循环结束后 i 的值是 4,所以所有函数都计算 4 * 2 = 8
修正方法:
def create_multipliers():
return [lambda x, i=i: i * x for i in range(5)]
修正原理:
1、这里我们在 lambda 函数中使用了默认参数 i=i
2、默认参数在函数定义时(即循环的每次迭代时)就被求值并固定
3、所以每个 lambda 函数都记住了自己创建时的 i 值
4、这样就能得到预期的 0 * 2, 1 * 2, 2 * 2, 3 * 2, 4 * 2 结果