Python:浅谈迭代器、生成器与协程的演化路径

news2024/11/24 4:41:28

“人生苦短,我用Python”,虽然说大量数学和统计分析库是一个重要优势,但是归根结底,Python的最大优势就是三点:

但是通常一般来讲,当扯到并发的时候,无论是多服务器、多进程、多线程、还是协程,事情都难以避免的开始变得复杂。我们把目光放到并发的最轻量级实现:协程上面,简单浅谈一下关于迭代器。

从迭代器说起

迭代器是访问集合元素的一种方式,无需知道集合的内部结构。任何实现了__iter____next__方法的对象都是迭代器。迭代器使得你可以逐个遍历容器内的元素,直到没有更多元素时抛出StopIteration异常。可以很容易实现一个自定义迭代器,这在自己实现一些需要迭代的数据结构式会有些作用:

class MyIterator:
    def __init__(self, max):
        self.current = 0
        self.max = max

    def __iter__(self):
        return self

    def __next__(self):
        if self.current >= self.max:
            raise StopIteration
        value = self.current
        self.current += 1
        return value


# 使用迭代器
for i in MyIterator(5):
    print(i)

输出:

0
1
2
3
4

迭代的艺术:生成器

生成器(Generators)是Python中一种特殊的迭代器。与传统的通过列表、元组等数据结构存储所有元素不同,生成器仅在需要时生成下一个值,大大节省了内存空间。生成器自动实现了迭代器协议,使得编写迭代器更为简单且内存效率更高。

如果想要自行通过迭代器实现与生成器相同功能,也并不困难,如下例子中调用__next__方法与生成器作用类似:

class FibonacciIterator:
    def __init__(self, max_count):
        self.max_count = max_count
        self.current_count = 0
        self.prev = 0
        self.curr = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.current_count >= self.max_count:
            raise StopIteration
        else:
            self.current_count += 1
            if self.current_count == 1:
                return self.prev
            elif self.current_count == 2:
                return self.curr
            else:
                self.prev, self.curr = self.curr, self.prev + self.curr
                return self.curr

# 使用自定义迭代器
fib_iter = FibonacciIterator(10)
print(fib_iter.__next__())
print(fib_iter.__next__())
print(fib_iter.__next__())
print(fib_iter.__next__())
print(fib_iter.__next__())
print(fib_iter.__next__())
print(fib_iter.__next__())

输出:

0
1
1
2
3
5
8

生成器最简单的形式是使用函数定义中的yield语句。每当遇到yield,函数就会暂停并返回一个值给调用者;当再次调用生成器的next()方法时,它会从上次停止的地方继续执行。上面的迭代器程序略显复杂,但是使用生成器之后,程序则变得简单清晰的多。下面的例子使用生成器实现了一样的功能,这可以很好的帮助理解迭代器的运行顺序:


def fibonacci_generator(max_count):
    prev, curr = 0, 1
    count = 0
    while count < max_count:
        yield prev
        prev, curr = curr, prev + curr
        count += 1

# 使用生成器
for num in fibonacci_generator(10):
    print(num)

输出:

0
1
1
2
3
5
8
13
21
34

Python的协程

在Python中,协程(Coroutines)通常被认为是生成器(Generators)的一个超集。它利用生成器的暂停与恢复机制,实现了非阻塞式的并发执行。协程在生成器的基础上进行了扩展,增加了更多的控制流特性,如能够接收输入、暂停执行等。协程是通过生成器实现的,生成器中的yield关键字可以用来实现协程的暂停和恢复执行的功能。Python协程实现,会使用asyncio包,并配合async/await语法糖。

可能只是我个人的YY,似乎Python的协程或多或少的借鉴了JS。从语法到实现方式都非常类似。在现代ES中,async/await语法糖是必不可少,几乎每个程序都会用到的,而Python也是用相同的关键字,从标准化角度,JS先于Python标准化了这两个语法糖。

一个简单的Python使用asyncio的例子如下所示:

import asyncio


async def task(name, delay):
    print(f"{name} start")
    await asyncio.sleep(delay)
    print(f"{name} end")


async def main():
    task1 = asyncio.create_task(task("TAsk1", 2))
    task2 = asyncio.create_task(task("TaSK2", 1))

    await task1
    await task2


asyncio.run(main()

输出:

TAsk1 start
TaSK2 start
TaSK2 end
TAsk1 end

上面代码中,通过asyncio.create_task创建了两个小任务,任务是异步运行的,并且程序必须等待两个任务都结束后,main才会返回。注意这里asyncio.create_task创建的task有些类似于JS的:

new Promise().then()

所以两个task是异步的。如果希望等待Task1完成后再运行Task2,则不需要通过asyncio.create_task创建task,直接再async函数调用前加入await即可,这是JS中一个常用的写法。如下:

import asyncio

async def main():
    await task("TAsk1", 2)
    await task("TaSK2", 1)

asyncio.run(main())

输出:

TAsk1 start
TAsk1 end
TaSK2 start
TaSK2 end

总结

从迭代器,到生成器,最后到协程,理解这个演化路径,可以更好地理解Python的协程机制。在此之后,加上对asyncio库的了解,即可熟练掌握Pythong的协程机制了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1861664.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《黑神话悟空》电脑配置要求

《黑神话&#xff1a;悟空》这款国内优秀的3A游戏大作&#xff0c;拥有顶级的特效与故事剧情&#xff0c;自公布以来便备受玩家期待&#xff0c;其精美的画面与流畅的战斗体验&#xff0c;对玩家的电脑配置提出一定要求。那么这款优秀的游戏需要什么样的电脑配置&#xff0c;才…

boost asio异步服务器(4)处理粘包问题tlv

粘包的产生 当客户端发送多个数据包给服务器时&#xff0c;服务器底层的tcp接收缓冲区收到的数据为粘连在一起的。这种情况的产生通常是服务器端处理数据的速率不如客户端的发送速率的情况。比如&#xff1a;客户端1s内连续发送了两个hello world&#xff01;,服务器过了2s才接…

一份简单的海外问卷,改变经济现状

在许多人看来&#xff0c;赚钱似乎总是与资金和技术密切相关。然而&#xff0c;即使没有丰富的资金和高超的技术&#xff0c;仍然有机会赚取可观的收入。 首先&#xff0c;需要明确的是&#xff0c;赚钱并非完全依赖于物质资本和技术能力。在这个充满机遇的时代&#xff0c;选…

鸿蒙开发网络管理:【@ohos.net.webSocket (WebSocket连接)】

WebSocket连接 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 使用WebSocket建立服务器与客户端的双向连接&#xff0c;需要先通过[createWebSocket]方法创建[WebSocket]对象&#xff0c;然后通…

python基础篇(4):range语句

1 功能介绍 range语句的功能是获得一个数字序列&#xff08;可迭代类型的一种&#xff09; 2 语法 语法1&#xff1a; range(num) 获取一个从0开始&#xff0c;到num结束的数字序列&#xff08;不含num本身&#xff09; 如range(5)取得的数据是&#xff1a;[0, 1, 2, 3, 4…

springboot多数据源应用,A服务依赖于B服务jar包,A服务和B服务业务数据分别入自己的库如何做?

上一节我们简单阐述了springboot多数据源如何配置。在实际的业务场景中我们常常遇到A服务依赖于B服务jar包&#xff0c;A服务和B服务业务数据分别入自己的库中。为何要这么做呢&#xff1f;比如B服务是日志SDK&#xff0c;A服务集成B服务来实现记录日志的功能&#xff0c;但是日…

安卓直装植物大战僵尸杂交版V2.1版完美运行

在移动游戏的世界里&#xff0c;植物大战僵尸无疑是一款深受玩家喜爱的经典游戏。如今&#xff0c;随着技术的发展和玩家需求的变化&#xff0c;植物大战僵尸杂交版V2.1版应运而生&#xff0c;为安卓用户带来了全新的游戏体验。 这一全新版本在原有游戏的基础上进行了多项创新…

TOP 5免费音频转换器,轻松搞定音频格式转换(白嫖党必备)

你是否正在寻找能提升音乐体验并满足各种需求的好用的免费音频转换器呢&#xff1f;如果是的话&#xff0c;那么请不用再找了&#xff01;在本篇文章中&#xff0c;我们汇总了顶级的音频格式转换软件&#xff0c;并且列出了其所兼容的操作系统及适合人群&#xff0c;从而满足你…

【PyTorch函数解析】einsum的用法示例

一、前言 einsum 是一个非常强大的函数&#xff0c;用于执行张量&#xff08;Tensor&#xff09;运算。它的名称来源于爱因斯坦求和约定&#xff08;Einstein summation convention&#xff09;&#xff0c;在PyTorch中&#xff0c;einsum 可以方便地进行多维数组的操作和计算…

PCL笔记二 之VS环境配置(不同版本Debug+Release编译)

PCL笔记二 之VS环境配置&#xff08;不同版本DebugRelease编译&#xff09; PCL官网&#xff1a;https://github.com/PointCloudLibrary/pcl/releases众所周知&#xff0c;PCL是一个用于点云处理并且依赖不少三方库的一个算法库&#xff0c;同时在编译配置环境时也很复杂&…

【ONLYOFFICE8.1桌面编辑器】强势来袭—— 一款全面的办公软件套件

在日常工作和学习中&#xff0c;我们经常需要处理各种文档、表格和演示文稿。一款功能强大、易于使用的办公软件成为我们提高工作效率、便捷沟通和展示想法的得力助手。 而ONLYOFFICE 8.1桌面编辑器正是一款全面、高效的办公软件&#xff0c;集合了Word、PPT、Excel的功能&…

如何设置windows计划任务

如何设置windows计划任务 前言&#xff1a;在工作过程中写了一个python脚本&#xff0c;用于调用jira接口查询bug单数量&#xff0c;想要在本地定时任务执行&#xff0c;每天发送到钉钉群提醒&#xff0c;写下操作步骤用于记录。 1. 准备 Python 脚本 确保你的 Python 脚本已…

暗影精灵8Pro声音没有了,这个方法可以解决,亲测有效!

这个OMEN by HP Gaming Laptop 16-k0xxx Windows 10 Sound Driver Mod &#xff0c;真的解决了我的大问题&#xff01; 如果你的暗影精灵8 Pro酷睿版突然变得哑巴了&#xff0c;扬声器和麦克风都发不出声音&#xff0c;那可能是声卡驱动出了问题。 别担心&#xff0c;我也是个…

Android简介

1. Android简介 Android是一种基于Linux内核的自由及开放源代码的操作系统。最初是由安迪鲁宾(Andy Rubin)开发的一款相机操作系统。2005年8月被Google收购。2007年11月&#xff0c;Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。…

8.12 矢量图层面要素单一符号使用七(随机标记填充)

文章目录 前言随机标记填充&#xff08;Random Marker Fill&#xff09;QGis设置面符号为随机标记填充&#xff08;Random Marker Fill&#xff09;二次开发代码实现随机标记填充&#xff08;Random Marker Fill&#xff09; 总结 前言 本章介绍矢量图层线要素单一符号中使用随…

手机照片压缩到20k以内免费,这几款心动软件快收好!

在数字化时代&#xff0c;手机拍照已成为我们记录生活的重要方式之一。然而&#xff0c;高清的照片也意味着占用着越来越多的手机存储空间。如果你正在为手机内存告急而烦恼&#xff0c;那么这几款手机照片压缩神器或许能成为你的救星&#xff01;它们不仅可以将照片轻松压缩至…

Three.js——第一篇:部署以及基础代码创建场景、GUI调整样式

three.js官网&#xff1a;three.js docs 中文技术文档1&#xff1a;| 麒跃科技 中文技术文档2&#xff1a;3. 开发和学习环境&#xff0c;引入threejs | Three.js中文网 很多教程一开始要大家自己部署three.js的中文本地部署&#xff0c;我就不弄了&#xff0c;我弄了半天也没…

大厂薪资福利篇第四弹:字节跳动

欢迎来到绝命Coding&#xff01; 今天继续更新大家最关心的 大厂薪资福利系列&#xff01; 往期分享&#xff1a; 福利开水喝不完&#xff1f;大厂薪资福利篇&#xff01;美团 职场文化发源地&#xff1f;大厂薪资福利篇&#xff01;阿里巴巴 给这么多&#xff01;还能带宠物上…

Adams Flex模块功能介绍

通过该教程对Adams Flex模块有基本的认知&#xff0c;为以后使用柔性体进行刚柔耦合做好基础学习。 有需要购买的可以邮箱&#xff08;digitaltwins126.com&#xff09;或站内信联系&#xff0c;谢谢&#xff01;

机器学习之数学基础(七)~过拟合(over-fitting)和欠拟合(under-fitting)

目录 1. 过拟合与欠拟合 1.1 Preliminary concept 1.2 过拟合 over-fitting 1.3 欠拟合 under-fitting 1.4 案例解析&#xff1a;黑天鹅 1. 过拟合与欠拟合 1.1 Preliminary concept 误差 经验误差&#xff1a;模型对训练集数据的误差。泛化误差&#xff1a;模型对测试…