回调函数、闭包概念、场景及python实战

在编写复杂或高度可扩展的程序时,我们经常需要用到回调函数闭包。这两个概念在函数式编程、事件驱动编程、框架设计、中间件等领域非常重要

1. 回调函数 (Callback Function)

1.1 什么是回调函数?

回调函数 是一个作为参数传递给其他函数的函数,该函数会在某个条件满足时(例如事件触发、异步操作完成、数据处理结束等)被"回调"执行。回调将控制权转交给用户定义的逻辑,使得高层代码可以调用底层代码注册的函数,从而实现"依赖倒置"(程序在运行时决定具体行为)。

1.2 在 Python 中的应用场景

  • 异步 I/O 或网络请求完成后通知主线程。

  • sort()sorted() 中的 key 参数。

  • GUI 编程中的按钮点击事件。

  • 数据处理管线中的自定义处理步骤。

python 复制代码
import time
from typing import Callable, Any

# 一个模拟异步处理的任务
def long_running_task(callback: Callable[[Any], None]) -> None:
    """模拟耗时操作,完成后调用回调函数"""
    print("任务开始...")
    time.sleep(2)               # 模拟耗时
    result = 42                 # 假设计算结果
    print("任务完成,准备调用回调")
    callback(result)            # 执行回调

def handle_result(data: Any) -> None:
    """用户自定义的回调函数"""
    print(f"回调处理结果: {data * 2}")

# 使用
long_running_task(handle_result)

输出:

任务开始...

任务完成,准备调用回调

回调处理结果: 84

1.4 同步回调 vs 异步回调

  • 同步回调:回调函数在调用者返回之前立即执行(如上例)。

  • 异步回调:回调函数延迟执行,可能由事件循环、线程池等触发。

python 复制代码
import threading

def async_task(callback):
    def run():
        print("异步线程工作...")
        time.sleep(1)
        callback("异步结果")
    threading.Thread(target=run).start()

def my_callback(msg):
    print(f"收到回调: {msg}")

async_task(my_callback)
print("主线程继续执行...")

注意 :Python 中的全局解释器锁(GIL)不影响回调的概念,但在高并发场景下建议使用 asyncioconcurrent.futures

2. 闭包 (Closure)

2.1 什么是闭包?

闭包 是一个函数,它"记住"了它被定义时所处的环境(即外部函数的局部变量),即使外部函数已经执行完毕,闭包仍然可以访问那些变量。闭包是 Python 中实现装饰器、工厂函数、延迟求值等技术的基础。

2.2 形成闭包的条件

  1. 存在嵌套函数(内部函数)。

  2. 内部函数引用了外部函数的局部变量。

  3. 外部函数将该内部函数作为返回值返回。

python 复制代码
def make_multiplier(factor: int):
    """外部函数,返回一个闭包"""
    def multiplier(x: int):
        return x * factor
    return multiplier

# 创建两个不同的闭包实例
double = make_multiplier(2)
triple = make_multiplier(3)

print(double(5))   # 10
print(triple(5))   # 15

# 检查闭包保存的变量
print(double.__closure__[0].cell_contents)  # 2

2.4 闭包的实际用途

  • 数据隐藏(类似轻量级的私有变量)。

  • 创建带有"记忆"的函数。

  • 替代某些简单的类(当只需要一个行为对象时)。

python 复制代码
def counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

c1 = counter()
c2 = counter()
print(c1())  # 1
print(c1())  # 2
print(c2())  # 1 (独立的状态)

2.5 闭包与 lambda 表达式

Lambda 函数也可以形成闭包,但受限于单表达式语法。

python 复制代码
def add_n(n):
    return lambda x: x + n

add_five = add_n(5)
print(add_five(10))  # 15

闭包可以生成回调函数:

python 复制代码
def make_callback_with_state(state):
    def callback(data):
        print(f"当前状态: {state}, 处理数据: {data}")
    return callback

callback_func = make_callback_with_state("ready")
# 以后把这个 callback_func 注册给某个事件处理系统

总结

  • 回调函数是实现"你完成时叫我"的标准化手段,是异步编程和事件循环的核心。

  • 闭包是 Python 中函数式编程的重要构件,它可以"捕获"外部变量,实现状态保持。

相关推荐
得想办法娶到那个女人1 小时前
项目中 TypeScript 类型推导 极简实战总结
前端·javascript·typescript
Beginner x_u2 小时前
前端八股整理(Vue 02)|组件通信、生命周期、v-if 与 v-show
前端·javascript·vue.js
一颗青果2 小时前
Cookie 与 Session 超详细讲解
服务器·前端·github
zs宝来了2 小时前
React 18 并发模式:Fiber 架构与时间切片
前端·javascript·框架
万物得其道者成2 小时前
Vue3 使用 Notification 浏览器通知,解决页面关闭后旧通知点击无法跳转问题
前端·vue.js·edge浏览器
ShineWinsu2 小时前
CSS 技术文章
前端·css
张风捷特烈2 小时前
状态管理大乱斗#02 | Bloc 源码全面评析
android·前端·flutter
将心ONE3 小时前
pathlib Path函数的使用
java·linux·前端
lingzhilab3 小时前
零知派——ESP32-S3 AI 小智 使用 Preferences NVS 实现Web配网持久化
前端