博客
关于我
python --- 协程
阅读量:805 次
发布时间:2023-03-05

本文共 5336 字,大约阅读时间需要 17 分钟。

协程与迭代器:Python异步编程的核心原理

协程的核心原理

协程(Coroutine),又称微线程或纤程,是一种用户级线程。与传统的操作系统线程不同,协程的切换和调度不是由操作系统控制的,而是由程序员自行管理。这种特性使得协程在处理I/O密集型应用时更加高效,适合需要多个入口点进行暂停和恢复的场景。

协程发展历程

Python的协程支持起源于生成器(Generators)的出现。最初,开发者通过生成器实现了协程功能。随后,在Python 3.5版本中,asyncawait关键字被引入,这些语法糖大大简化了协程的书写和使用,使得协程代码更加易读和维护。如今,Python内置的asyncio标准库和诸多第三方库(如greenletgeventTornado)共同构成了现代Python协程生态系统。

协程的工作原理

Python中的协程依赖于事件循环(Event Loop)来实现异步操作。事件循环负责监听和分发事件,如网络请求、文件IO等。当协程遇到await表达式时,它会将控制权交还给事件循环,并挂起自身的执行。这样,事件循环可以继续处理其他任务,直到被挂起的协程可以继续执行时,事件循环再将控制权交回给该协程。

这种协程模型使得Python能够在不阻塞主线程的情况下,高效地执行多个异步任务,特别适合处理I/O密集型应用。


迭代器的核心概念

迭代的概念

迭代是指通过for循环遍历某一系列的取值的过程。例如:

for i in [1,2,3,4,5]:    print(i)

可迭代对象

可迭代对象是指能够支持for循环操作的对象。这些对象需要实现__iter__方法。常见的可迭代对象包括列表、元组、字典、集合、range等。例如:

from collections.abc import Iterableprint(isinstance([1,2,3], Iterable))  # 输出: True

迭代器对象

迭代器对象是指通过实现__iter____next__方法创建的对象。这些对象能够像生成器一样提供一系列的值。例如:

from collections.abc import Iterable, Iteratorclass Mylist(object):    def __init__(self):        self.mylist = []        def append_item(self, item):        self.mylist.append(item)        def __iter__(self):        return MyIterator(self.mylist)class MyIterator(object):    def __init__(self, mylist):        self.mylist = mylist        self.current_index = 0    def __next__(self):        if self.current_index < len(self.mylist):            res = self.mylist[self.current_index]            self.current_index += 1            return res        else:            raise StopIteration# 创建可迭代对象my_list = Mylist()my_list.append_item(1)my_list.append_item(2)# 获取迭代器对象my_it = iter(my_list)print('可迭代对象:', isinstance(my_list, Iterable))  # 输出: Trueprint('迭代器对象:', isinstance(my_it, Iterator))  # 输出: True# 遍历并打印结果while True:    try:        value = next(my_it)        print(value)    except StopIteration:        break

迭代器的应用场景

迭代器的核心功能是通过next()函数获取下一个数据值。在迭代器中,每次返回的数据值不是从一个现有的数据集合中读取,而是通过程序逻辑计算生成的。例如,生成斐波拉契数列的迭代器:

class Feibonaqie(object):    def __init__(self, num):        self.num = num        self.a = 0        self.b = 1        self.current_index = 0    def __iter__(self):        return self    def __next__(self):        if self.current_index < self.num:            result = self.a            self.a, self.b = self.b, self.a + self.b            self.current_index += 1            return result        else:            raise StopIteration# 创建斐波拉契数列迭代器res = Feibonaqie(5)print(list(res))  # 输出: [0, 1, 1, 2, 3]

迭代器通过记录当前数据的位置,以便获取下一个位置的值,这使得它在性能敏感的场景中非常有用。


生成器的核心概念

生成器(Generator)是Python的一种特殊迭代器。只要在函数定义中包含yield关键字,该函数就被称为生成器。生成器不需要像普通迭代器那样手动实现__iter____next__方法。

生成器的创建方法

  • 使用元组推导式

    res = (i * 2 for i in range(5))print(res)  # 输出: 
    at 0x...>print(tuple(res)) # 输出: (0, 2, 4, 6, 8)
  • 使用yield关键字

    def coroutine_example():    while True:        value = yield 0        print(f"Received value: {value}")        value = yield value + 1        print(f"Received value: {value}")c = coroutine_example()print('result:', next(c))  # 输出: 0print('result2:', c.send(2))  # 输出: 3print('result4:', c.send(4))  # 输出: 0
  • 生成器的高级功能

  • yield from

    yield from用于支持子生成器。例如:

    def gen():    while True:        value = yield 0        print(f"Received value: {value}")        value = yield value + 1        print(f"Received value: {value}")def ren():    yield from gen()c = ren()print('result:', next(c))  # 输出: 0print('result2:', c.send(2))  # 输出: 3print('result4:', c.send(4))  # 输出: 0
  • asyncio.coroutine

    在异步编程中,asyncio.coroutine装饰器用于标识协程函数。例如:

    import timeimport asyncio@asyncio.coroutinedef taskIO_1():    print('开始运行IO任务1...')    yield from asyncio.sleep(2)  # 模拟耗时2秒的IO任务    print('IO任务1已完成,耗时2秒')    return taskIO_1.__name__@asyncio.coroutinedef taskIO_2():    print('开始运行IO任务2...')    yield from asyncio.sleep(3)  # 模拟耗时3秒的IO任务    print('IO任务2已完成,耗时3秒')    return taskIO_2.__name__async def main():    tasks = [taskIO_1(), taskIO_2()]    done, pending = yield from asyncio.wait(tasks)    for r in done:        print('协程无序返回值:', r.result())if __name__ == '__main__':    start = time.time()    loop = asyncio.get_event_loop()    try:        loop.run_until_complete(main())    finally:        loop.close()    print('所有IO任务总耗时%.5f秒' % float(time.time() - start))

  • 异步编程的实现原理

    异步编程通过协程实现非阻塞的并发处理。协程的执行依赖于事件循环,事件循环负责调度协程的执行。Python的asyncawait关键字使得协程代码更加简洁易读。

    asyncawait的作用

    async def定义了一个异步函数,该函数可以使用await关键字挂起执行,等待异步任务完成。例如:

    import timeimport asyncioasync def taskIO_1():    print('开始运行IO任务1...')    await asyncio.sleep(3)  # 模拟耗时3秒的IO任务    print('IO任务1已完成,耗时3秒')    return taskIO_1.__name__async def taskIO_2():    print('开始运行IO任务2...')    await asyncio.sleep(2)  # 模拟耗时2秒的IO任务    print('IO任务2已完成,耗时2秒')    return taskIO_2.__name__async def main():    result = await asyncio.gather(taskIO_1(), taskIO_2())    print(result)if __name__ == '__main__':    start = time.time()    loop = asyncio.get_event_loop()    try:        loop.run_until_complete(main())    finally:        loop.close()    print('所有IO任务总耗时%.5f秒' % float(time.time() - start))

    异步任务的调度

    事件循环通过asyncio.wait()等函数等待多个任务完成,返回已完成和未完成任务的集合。如需按顺序等待任务完成,可使用asyncio.gather()函数。例如:

    async def main():    result = await asyncio.gather(taskIO_1(), taskIO_2())    print(result)# 或者async def main():    tasks = [taskIO_1(), taskIO_2()]    done, pending = await asyncio.wait(tasks)    for r in done:        print('协程无序返回值:', r.result())

    总结

    协程和生成器是Python异步编程的核心技术。协程通过事件循环实现非阻塞的任务调度,而生成器则为协程提供了一种灵活的执行方式。理解这些概念是掌握现代Python异步编程的基础。

    转载地址:http://asafk.baihongyu.com/

    你可能感兴趣的文章
    python logging模块学习
    查看>>
    python mac地址_python中MAC地址打包问题
    查看>>
    python manage.py syncdb Unknown command: 'syncdb'问题解决方法
    查看>>
    Python map() 函数 和 numpy mean()函数
    查看>>
    Python Matplotlib Box并排绘制两个数据集
    查看>>
    Python Matplotlib 中如何用 plt.savefig 存储图片
    查看>>
    Python matplotlib 中更换画布背景颜色
    查看>>
    Python进阶03 模块
    查看>>
    python matplotlib简单使用
    查看>>
    Python mock Patch os.environ 和返回值
    查看>>
    Python mock 修补另一个函数调用的函数
    查看>>
    python mqtt 客户端实现
    查看>>
    Python Multiprocessing - 将类方法应用于对象列表
    查看>>
    Python multiprocessing.Queue 与 multiprocessing.manager().Queue()
    查看>>
    Python multiprocessing使用详解
    查看>>
    python mysql 基于 sqlalvhrmy_Python操作MySQL:pymysql和SQLAlchemy
    查看>>
    python mysql 布尔类型_python语言的基础学习:基本类型,函数,面向对象,模块,mysql数据库...
    查看>>
    Python NLP完整项目实战教程(1)
    查看>>
    Python NLP自然语言处理详解
    查看>>
    python nltk nltk_data 离线安装,chatterbot
    查看>>