程序代码篇---python回调函数&异步编程


文章目录

  • 前言
  • 第一部分:Python的回调函数
    • 1.基本概念
    • 2.如何实现
      • 定义回调函数:
      • 定义主函数:
      • 例子
    • 3.回调函数的应用场景
      • 事件处理
      • 异步编程
      • 库和框架
      • 注意事项
        • 调用时机
        • 错误处理
        • 闭包
  • 第二部分:async和await关键字
    • 1.异步编程的概念
    • 2.async
      • 定义
      • 用法
      • 特性
    • 3.await
      • 定义
      • 用法
      • 特性
    • 4.异步编程的例子
    • 5.注意事项
  • 总结


前言

以上就是今天要讲的内容,本文简单介绍了Python中的回调函数以及异步编程。


第一部分:Python的回调函数

在Python中,回调函数是一种编程范式,它允许我们将一个函数作为参数传递给另一个函数。这个作为参数传递的函数(即回调函数)可以在另一个函数执行到某个点时被调用。回调函数在事件驱动编程、异步编程和某些库和框架中非常常见。

以下是关于回调函数的详细解释:

1.基本概念

定义:回调函数是一个你定义的函数,但不是由你来调用。你将这个函数作为参数传递给另一个函数,这个另一个函数在适当的时候会调用你的函数。
目的:回调函数允许代码的模块化和解耦,使得我们可以编写更灵活和可重用的代码。

2.如何实现

定义回调函数:

这只是一个普通的函数,可以接受任意数量的参数。

def my_callback_function(param):
    print(f"Callback function called with {param}")

定义主函数:

主函数接受一个函数作为参数,这个参数就是回调函数。

def main_function(callback):
    # 做一些操作
    # ...
    # 调用回调函数
    callback("some data")

调用主函数,传递回调:
当调用main_function时,我们将my_callback_function作为参数传递。

main_function(my_callback_function)

例子

下面是一个完整的例子,演示了如何使用回调函数:

def print_hello(name):
    print(f"Hello, {name}")

def greeter(callback, name):
    callback(name)

使用print_hello作为回调函数

greeter(print_hello, "Alice")

运行这段代码,输出将是:

Hello, Alice

3.回调函数的应用场景

事件处理

事件处理:在**图形用户界面(GUI)**编程中,当用户执行某些操作(如点击按钮)时,可以注册一个回调函数来响应事件。

异步编程

异步编程:在执行异步操作(如网络请求、文件I/O)时,可以提供一个回调函数,以便在操作完成时执行。

库和框架

库和框架:许多库和框架允许你传入回调函数来自定义其行为,例如排序函数、过滤函数等。

注意事项

调用时机

调用时机:回调函数可能在任何时候被调用,这取决于主函数的实现。

错误处理

错误处理:回调函数中的错误可能会影响主函数的执行,因此需要妥善处理。

闭包

闭包:如果回调函数在定义它的作用域之外被调用,它可能形成一个闭包,能够访问定义时的作用域中的变量。
通过使用回调函数,Python程序员可以编写更加灵活和可扩展的代码。不过,也需要注意回调地狱(callback hell)的问题,即当回调函数嵌套太多层时,代码会变得难以理解和维护。为了解决这个问题,可以使用异步编程的async和await关键字,或者使用Promise等模式

第二部分:async和await关键字

1.异步编程的概念

异步编程是一种编程范式,允许程序在等待某些操作(如I/O操作、网络请求等)完成时继续执行其他任务。这与传统的同步编程相反,在同步编程中,程序在等待一个操作完成时会阻塞,直到该操作完成。

2.async

定义

定义:async是一个用于定义异步函数的关键字。异步函数与普通函数不同,它们在执行时可以暂停并在适当的时候恢复执行

用法

用法:将async关键字放在函数定义的前面,如下所示:

async def my_async_function():

特性

特性:异步函数在调用时不会立即执行,而是返回一个协程对象(coroutine object)。协程对象需要通过事件循环(event loop)来调度执行

3.await

定义

定义:await关键字用于等待一个协程完成。它只能在异步函数内部使用

用法

用法:在异步函数内部,使用await关键字调用另一个异步函数

async def another_async_function():
await some_async_operation()

特性

特性:当await被调用时,它会暂停当前协程的执行,直到被等待的协程完成。在此期间,事件循环可以运行其他协程

4.异步编程的例子

以下是一个使用async和await的简单例子:

import asyncio

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    print(f"started at {time.strftime('%X')}")

    await say_after(1, 'hello')
    await say_after(2, 'world')

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

在这个例子中:

  1. say_after是一个异步函数,它等待指定的延迟时间后打印一条消息
  2. main也是一个异步函数,它调用say_after两次,每次等待不同的时间。
  3. asyncio.run(main())是启动事件循环并运行main协程的方法
  4. 顺序执行但非阻塞:虽然say_after函数是顺序调用的,但它们是异步执行的。这意味着在等待say_after(1, ‘hello’)完成时,程序不会阻塞,而是可以继续执行其他操作(如果有)。在这个例子中,由于没有其他操作,所以实际上它是顺序执行的。
  5. 并发潜力:如果有其他异步任务需要执行,它们可以在等待say_after函数完成时并发执行。例如,如果有另一个异步函数do_something_else,你可以在await say_after(1, ‘hello’)之后立即调用它,而不需要等待’hello’打印完成。
  6. 资源效率:异步编程允许单线程程序在等待I/O操作(如asyncio.sleep模拟的)完成时执行其他任务。这比使用多线程来处理并发I/O操作要高效得多,因为多线程会增加上下文切换的开销。
import asyncio
import time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    print(f"started at {time.strftime('%X')}")

    # 创建两个协程
    task1 = asyncio.create_task(say_after(1, 'hello'))
    task2 = asyncio.create_task(say_after(2, 'world'))

    # 不等待每个协程单独完成,而是并发地运行它们
    # 这里的await不会阻塞其他协程的执行
    await task1
    await task2

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

在这个修改后的版本中,我们使用了asyncio.create_task()来创建两个任务,这两个任务会并发执行。这里的关键是,await关键字现在用于等待两个任务的同时完成,而不是分别等待每个say_after函数。由于这两个任务是并发执行的,所以整体程序的执行时间将接近于最长的单个任务执行时间(在这个例子中是2秒),而不是各个任务执行时间的总和(原来的3秒)。

5.注意事项

  1. 只能在异步函数中使用await:await关键字只能在async def定义的异步函数中使用
  2. 事件循环:异步函数需要事件循环来运行。asyncio.run()是一个便捷的方法来运行最高层级的异步函数。
  3. 并发与并行:asyncio提供的是并发而不是并行。虽然多个协程可以并发执行,但它们实际上是在单个线程中通过事件循环进行调度。
  4. 性能考虑:异步编程可以提高I/O密集型应用程序的性能,但对于CPU密集型任务,过多的协程可能会导致性能下降。
    通过使用async和await,Python程序员可以编写更加清晰和易于维护的异步代码,这对于网络应用、数据库操作和其他需要等待外部资源的场景非常有用。

总结

以上就是今天要讲的内容,本文仅仅简单介绍了Python中的回调函数以及异步编程。

你可能感兴趣的:(程序代码篇,python,前端,开发语言,学习,程序人生,回调函数,异步编程)