3.1 认识闭包
闭包就是一个捕获其周围作用域中的变量的函数, 即使在这个作用域执行完毕之后。也就是说,闭包能够“记住”来自其外部作用域的变量的值, 并且在这个作用域不再活动时仍然可以使用这些变量。
为了理解闭包是如何工作的,来看以下例子:
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
closure = outer_function(10)
print(closure(5)) # 输出:15
让我们看看这里写了什么:
外部函数(outer_function)
:这个函数接受
参数x
并定义一个内部函数inner_function
,
它接受参数y
并返回x
和y
的和。
inner_function
并没有在outer_function
内调用,而只是被声明。
内部函数(inner_function)
:这个函数从
outer_function
返回,并在内部保留对传递给
outer_function
的x
值的引用。
闭包:变量closure
变成一个
闭包,它“记住”x
的值(在这个例子中为10),可以在调用时使用。
一般来说,第一次接触闭包时,大家都很难理解。所以让我们通过例子来提升你对闭包的理解。
3.2 闭包的使用例子
创建生成器函数
闭包可以用于创建生成器函数,生成值的序列。
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
counter = make_counter()
print(counter()) # 输出:1
print(counter()) # 输出:2
print(counter()) # 输出:3
解释:
生成器函数(make_counter)
:这个函数创建了一个
变量count
并返回一个内部函数counter
,
后者增加count
的值并返回它。
闭包:函数counter
保存了count
变量的状态,
并可以在每次调用时改变它。
创建带有配置的函数
闭包可以用于创建带有预定义配置的函数。
def make_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 输出:10
print(triple(5)) # 输出:15
解释:
配置函数(make_multiplier)
:这个函数
接收一个乘数factor
并返回一个内部函数multiplier
,
它将输入值乘以factor
。
闭包:函数double
和triple
是闭包,
它们保存了自己的factor
值并用来乘数。
带有参数的过滤数据
闭包可以用于创建带有参数的过滤函数。
def make_filter(threshold):
def filter_func(value):
return value > threshold
return filter_func
filter_above_10 = make_filter(10)
data = [5, 10, 15, 20]
filtered_data = list(filter(filter_above_10, data))
print(filtered_data) # 输出:[15, 20]
解释:
过滤函数(make_filter)
:这个函数接收
一个阈值threshold
并返回一个内部函数filter_func
,
它检查值是否超过阈值。
闭包:函数filter_func
保存了threshold
的值,并用它来过滤数据。
3.3 闭包的优缺点
使用闭包的优点
状态封装:闭包允许将状态封装在函数中, 避免使用全局变量,提高代码的可读性和可维护性。
灵活性:闭包可以用于创建具备特定配置或行为的 函数,使得代码更加灵活和适应性更强。
函数式编程:闭包在函数式编程中是一个重要的 概念,允许创建高阶函数和其他函数式结构。
限制和潜在问题
尽管有很多优点,闭包也有一些限制:
内存使用:闭包可能会保留对 不再使用的对象的引用,导致内存泄漏。
调试复杂性:闭包可能会使调试代码变得复杂, 因为变量状态可能并不明显。
GO TO FULL VERSION