python补充

python中的异步、事件循环、协程、Ruff分析工具 装饰器、迭代器、生成器、zip
NOTE
  • 事件循环:管理和调度异步任务的核心组件。
  • 协程:使用 async def 定义的函数,可以在事件循环中异步运行。
  • 任务:由事件循环调度的协程对象。
  • Future:表示一个异步操作的最终结果,类似于 JavaScript 中的 Promise。

异步

在 Python 中,将异步方法转换为同步协程可以通过 asyncio 库实现。这种转换通常用于在同步代码中调用异步函数,确保主线程不被阻塞。

Python中的异步编程的核心语法就是async/await两个关键字,主要涉及的概念就是协程(coroutine)。

协程

尽量提前了解线程、进程、同步、异步、并行、并发 简单来说,协程就是在一个线程(thread)里通过事件循环(event loop)模拟出多个线程并发的效果。

关于协程(coroutine)

    1. 使用async def定义的函数是一个coroutine,这个函数内部可以用await关键字。
    1. 使用async def定义的函数,调用之后返回的值,是一个coroutine对象,可以被用于await或者asyncio.run等

Python 引入了 async/await 语法来支持异步编程。当我们在函数定义前加上 async 关键字时,这个函数就变成了一个"协程"(coroutine)。而 await 关键字则用于等待一个协程完成。让我们改写上面的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import asyncio
import random
import time

async def process_item(item):
    print(f"处理中:{item}")
    # async 定义的函数变成了协程
    process_time = random.uniform(0.5, 2.0)
    await asyncio.sleep(process_time)  # await 等待异步操作完成,说明这个seleep也是个协程
    return f"处理完成:{item},耗时 {process_time:.2f} 秒"

async def process_all_items():
    items = ["任务A", "任务B", "任务C", "任务D"]
    # 创建任务列表
    tasks = [
        asyncio.create_task(process_item(item))
        for item in items
    ]
    print("开始处理")
    results = await asyncio.gather(*tasks)
    return results

async def main():
    start = time.time()
    results = await process_all_items()
    end = time.time()
    
    print("\n".join(results))
    print(f"总耗时:{end - start:.2f} 秒")

if __name__ == "__main__":
    asyncio.run(main())

事件循环

事件循环是一个设计模式,用于在单线程中处理多个并发任务。它不断地检查是否有待处理的事件,并调用相应的回调函数。

Ruff分析工具

是一个python代码检查工具,可以高效检查代码规范,比如类型问题、导入不用的包等等

装饰器

用来修改或增强函数的行为 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。

1
2
3
4
def test():
    print("hello world")
f = test
f()

函数对象都有个__main__属性

1
2
3
4
>>> test.__name__
'test'
>>> f.__name__
'test'

现在,假设我们要增强test()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改test()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。 例如我们要实现一个日志装饰器(想在函数调用的时候打印一些日志):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def log(func):
    def inner(*args, **kws):
        print(f"调用{func.__name__}函数的一些日志信息……")
        return func(*args, **kws)
    return inner

@log  # 等价于 now = log(now)
def now():
    print('2024-6-1')

now()

其实这种就是一种闭包,所以装饰器是伴随着闭包的 闭包主要就三点:

    1. 内外嵌套
    1. 内调用外(也可使用外属性、变量)
    1. 外返回内

迭代器

实现__iter__()和__next__()其实就是实现了一个迭代器,可被用于迭代操作(仅仅一次) iter():返回迭代器对象本身 next():返回下一个元素,没有元素时抛出 StopIteration

生成器

生成器的核心原理是 yield 关键字实现的“暂停和恢复”机制。它将一个普通的函数转变为一个可以记住自身状态的生产者,实现了:

  • 惰性求值:按需生成,极大节省内存。
  • 流式处理:非常适合处理数据流、大文件和无限序列。
  • 协同程序:通过 .send() 等方法,可以实现简单的双向通信,是 Python 中协程和异步编程的基础。

上面这个之前又被在面试中问到过,还有异步编程中的协程

迭代器和生成器都只能遍历一次哦,内存高效型

zip

zip对象本质上是个迭代器对象

1
2
3
4
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
zipped = zip(names, ages)
print(zipped) 

map

map() 函数将一个函数应用于一个或多个可迭代对象中的所有元素,并返回一个 map 对象(迭代器)。 可以与lambda配合使用