闭包

Python SELF ZH
第 13 级 , 课程 3
可用

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并返回xy的和。 inner_function并没有在outer_function 内调用,而只是被声明。

内部函数(inner_function):这个函数从 outer_function返回,并在内部保留对传递给 outer_functionx值的引用。

闭包:变量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

闭包:函数doubletriple是闭包, 它们保存了自己的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 闭包的优缺点

使用闭包的优点

状态封装:闭包允许将状态封装在函数中, 避免使用全局变量,提高代码的可读性和可维护性。

灵活性:闭包可以用于创建具备特定配置或行为的 函数,使得代码更加灵活和适应性更强。

函数式编程:闭包在函数式编程中是一个重要的 概念,允许创建高阶函数和其他函数式结构。

限制和潜在问题

尽管有很多优点,闭包也有一些限制:

内存使用:闭包可能会保留对 不再使用的对象的引用,导致内存泄漏。

调试复杂性:闭包可能会使调试代码变得复杂, 因为变量状态可能并不明显。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION