授课语音

Python 闭包(Closure)知识点

一、闭包概述

1. 什么是闭包

闭包(Closure)是指一个函数(通常是嵌套函数)能够访问并记住其外部函数的变量,即使外部函数已经执行完毕。闭包的一个关键点是,嵌套函数不仅能够访问外部函数的变量,还能够修改这些变量。

在 Python 中,闭包的作用域可以跨越函数的调用。闭包的典型应用是维护状态和避免全局变量污染。

2. 闭包的特点

  • 外部函数定义了一个内部函数
  • 内部函数引用了外部函数的变量
  • 外部函数的变量在外部函数执行结束后仍然能被内部函数访问
  • 外部函数返回了内部函数,使得内部函数成为闭包。

二、闭包的工作原理

  1. 外部函数执行:外部函数会创建一个作用域,并在这个作用域内定义内部函数。
  2. 返回内部函数:外部函数返回内部函数的引用,不会立即执行,而是将其作为结果返回。
  3. 闭包的作用:内部函数引用外部函数的局部变量,形成闭包。即使外部函数执行结束,闭包依然可以访问这些局部变量。

三、闭包的代码案例

1. 基本的闭包示例

# 外部函数
def outer_function(x):
    # 外部函数中的变量 x
    def inner_function(y):
        # 内部函数引用了外部函数的变量 x
        return x + y
    # 返回内部函数的引用
    return inner_function

# 创建闭包
closure = outer_function(10)  # outer_function(10) 返回的是内部函数的引用

# 使用闭包
result = closure(5)  # 内部函数被调用,传入 5
print(result)  # 输出: 15

注释

  • outer_function 是外部函数,接收一个参数 x
  • inner_function 是内部函数,它引用了外部函数的变量 x
  • 外部函数返回内部函数的引用,形成闭包 closure,它可以继续访问 x 的值。
  • 即使 outer_function 已经执行结束,闭包依然能够访问 x,并且根据不同的输入计算结果。

2. 闭包用于维护状态

# 定义一个闭包来维护计数器的状态
def counter():
    count = 0  # 外部函数中的变量 count,用于记录次数
    def increment():
        nonlocal count  # 关键字 nonlocal 表示引用外部函数的变量
        count += 1  # 增加计数
        return count
    return increment

# 创建一个计数器闭包
counter1 = counter()

# 调用闭包
print(counter1())  # 输出: 1
print(counter1())  # 输出: 2
print(counter1())  # 输出: 3

注释

  • counter 函数返回了 increment 函数的引用,increment 函数引用并修改了外部的 count 变量。
  • nonlocal 关键字用于声明变量 count 是外部函数的局部变量,避免重新定义一个局部变量。
  • 每次调用 counter1(),计数器的状态都会更新,从而实现计数功能。

3. 闭包与返回多个值

# 创建一个闭包来返回多个相关函数
def arithmetic_operations(x):
    def add(y):
        return x + y
    def subtract(y):
        return x - y
    def multiply(y):
        return x * y
    return add, subtract, multiply

# 创建闭包
add_function, subtract_function, multiply_function = arithmetic_operations(10)

# 使用闭包返回的函数
print(add_function(5))  # 输出: 15
print(subtract_function(5))  # 输出: 5
print(multiply_function(5))  # 输出: 50

注释

  • arithmetic_operations 返回了三个嵌套函数:addsubtractmultiply
  • 每个嵌套函数都可以引用外部函数的变量 x,并执行不同的算术操作。
  • 使用闭包可以灵活地封装不同的操作,避免重复代码。

四、闭包常见应用

  1. 避免全局变量污染: 闭包能够有效避免在全局作用域中定义大量的变量,保持程序的清晰和可维护性。

  2. 函数工厂: 闭包可以生成具有相似行为但稍有不同的多个函数。例如,构造不同的计数器、数学操作等。

  3. 回调函数与事件处理: 在异步编程和事件驱动编程中,闭包经常被用来保存事件的状态或回调函数的状态。


五、闭包的注意事项

  1. 闭包捕获的变量是引用而非拷贝: 闭包函数会捕获外部函数的变量引用,而非拷贝。因此,闭包内使用的外部变量值是动态变化的。

  2. 避免闭包引用未定义的变量: 在使用闭包时,确保内部函数能够正确引用外部函数定义的变量,避免引用未定义的变量。

  3. nonlocalglobal

    • nonlocal 用于修改外部函数(但非全局)的变量。
    • global 用于修改全局作用域中的变量。

六、总结

闭包是 Python 中一个非常强大的特性,它允许函数记住并访问其外部函数的变量。通过闭包,程序员可以有效地管理状态,避免使用全局变量,并可以灵活地生成和封装多种行为。理解闭包的工作原理是掌握 Python 函数式编程的关键。

去1:1私密咨询

系列课程: