【python】生成器

生成器

直接总结

  1. 创建生成器的方法
    1. 生成器表达式:(i for i in [1, 2])
    2. yield: 函数中出现yield这个函数就是生成器,函数(生成器)执行到yield时会返回yield后面的值,并暂停,知道下次被唤醒后会从暂停处接着执行
  2. 迭代生成器: 生成器实现了python迭代协议,可以使用next()for迭代
  3. 向生成器发送消息:如果yield出现在表达式右边,下一次生成器被send()唤醒时,上一个yield会接收send()发过来的消息赋值给上一个yield左边的变量。
  4. 唤醒生成器:
    1. next():唤醒生成器,让他运行到下一个yield处,返回yield出来的值
    2. send():唤醒生成器,并给生成器发送一个消息,同时让他运行到下一个yield处,返回yield出来的值,不能直接一开始就发送具体的数据
  5. 停止生成器:close()
  6. 发送异常:throw(type, val)
  7. yield from

创建与使用生成器

直接使用生成器表达式就可以快速创建一个生成器

gen = (i for i in range(10))
print(type(gen))
for i in gen:print(i, end=" ")# <class 'generator'>
# 0 1 2 3 4 5 6 7 8 9 

生成器实现了__next__可以使用next()来获取下一个值,当然也可以使用for循环遍历

更加常见的创建生成器的方式是使用yield关键字,一个函数如果出现yield关键字这个函数就会变成生成器,当函数运行到yield时会暂停下来,”返回“一个结果,下一次唤醒生成器时,函数会从停下来的地方继续运行

def builder_demo():yield 0yield 1return 3if __name__ == '__main__':bd = builder_demo()print(type(bd))print(next(bd))print(next(bd))print(next(bd))print(next(bd))
<class 'generator'>
0
1
Traceback (most recent call last):File "E:/python/coroutine_test.py", line 12, in <module>print(next(bd))
StopIteration: 3

当没有下一个元素时调用next会抛出StopIteration异常,return的值会作为异常的值

if __name__ == '__main__':bd = builder_demo()while True:try:print(next(bd))except StopIteration as e:print(f'result is {e.value}')break
0
1
result is 3

yield不但可以“传递出值”,也可以接收值

def builder_demo():news = yield 0print(f'news:  {news}')news1 = yield 1print(f'new1: {news1}')return 3if __name__ == '__main__':bd = builder_demo()print(next(bd))result1 = bd.send("hello")print(result1)result2 = bd.send("hello2")print(result2)
0
news:  hello
1
new1: hello2
Traceback (most recent call last):File "E:python/coroutine_test.py", line 14, in <module>result2 = bd.send("hello2")
StopIteration: 3

往暂停处传递消息使用生成器的send()方法,这个方法还可以自动迭代到生成器中的下一个对象(有next())的作用。

生成器是先yield出数据,等到下一次生成器被唤醒时,才会接收send()的数据,然后再yield出下一个数据,所以不能一开始就直接调用send()发送具体的值,会抛出TypeError

TypeError: can't send non-None value to a just-started generator

应该先执行一次next()或执行一次generator.send(None),让生成器yield出数据,send(None)的作用与next()基本一样

生成器也可以停止,使用close()方法

def builder_demo():news = yield 0print(f'news:  {news}')news1 = yield 1print(f'new1: {news1}')yield 4yield 5return 3if __name__ == '__main__':bd = builder_demo()# print(next(bd))print(bd.send(None))result1 = bd.send("hello")print(result1)result2 = bd.send("hello2")print(result2)bd.close()print(next(bd))
0
news:  hello
1
new1: hello2
4
Traceback (most recent call last):File "E:python/coroutine_test.py", line 20, in <module>print(next(bd))
StopIteration

close()之后再使用next(),会抛出StopIteration异常

除此之外,还可以向生成器发送异常

if __name__ == '__main__':bd = builder_demo()print(bd.send(None))bd.throw(Exception, TypeError("throw new error"))print(next(bd))
0
Traceback (most recent call last):File "E:python/coroutine_test.py", line 19, in <module>bd.throw(Exception, TypeError("throw new error"))File "E:python/coroutine_test.py", line 2, in builder_demonews = yield 0
TypeError: throw new error

yield from

yield from 是python3.3 PEP380 新添加的特性,它允许将一个生成器的部分操作委派给另一个生成器,除了向子生成器委派任务,yield from也可以直接作用于迭代器,将迭代器中的每个对象逐一yield出来,如:

def demo(*args, **kwargs):for i in args:for j in i:yield j
# 等价于
def demo(*args, **kwargs):for i in args:yield from i

上面的函数其实就是itertools.chain() 作用是将多个迭代器中的元素迭代出来

生成器嵌套

1、调用方:调用委派生成器的客户端(调用方)代码
2、委托生成器:包含yield from表达式的生成器函数
3、子生成器:yield from后面加的生成器函数

yield from 可以架设一个调用方子生成器之间的双向桥梁

final_result = {}def calculate():total = 0nums = []while True:info = yieldif not info:breaktotal += infonums.append(info)# return 的值会被赋值给yield from 左边的变量return total, numsdef middle(key: str, gen):while True:final_result[key] = yield from gen()print(final_result)def main():data = {"apple": [230, 569, 234, 776],"banana": [564, 213, 798, 327],"strawberry": [98, 76, 120, 436, 55],"orange": [78, 67, 345, 124]}for key, value in data.items():# 不要传递calculate()!mid = middle(key, calculate)mid.send(None)  # 初激for v in value:mid.send(v)mid.send(None)if __name__ == '__main__':main()

为什么“多此一举”架设一个“桥梁”?

  • yield from 在内部处理了大量可能的异常,简化开发,提高代码安全性和可读性

生成器的作用

  1. 适用于对大量数据的处理:如果要对产生的大量数据进一步处理时,使用容器就只能先得到所有要处理的数据,存到容器,再逐个对容器中的数据遍历,再加工,最后得到目标数据,这样第一步产生的“中间数据”只用一次,但仍需大量空间储存;使用生成器可以产生一个,加工一个,节约内存,提高效率
  2. 用于协程

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

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

相关文章

python redis 性能测试台_Redis性能测试

Redis 性能测试Redis 性能测试是通过同时执行多个命令实现的。Redis性能测试主要是通过src文件夹下的redis-benchmark来实现(Linux系统下)语法redis 性能测试的基本命令如下&#xff1a;redis-benchmark [option] [option value]实例以下实例同时执行 10000 个请求来检测性能&a…

Java IO 系统

Java IO系统 File类 用来处理文件目录&#xff0c;既可以代表一个特定文件的名称&#xff0c;也可以代表一组文件的名称&#xff0c;如果代表的是一个文件组&#xff0c;可以调用File.list()方法返回一个字符数组。 list()不传递任何参数时返回该目录下所有文件或文件名的字…

Linux Crontab 任务管理工具命令以及示例

Crontab 是 Linux 平台下的一款用于循环执行例行任务的工具,Linux 系统由 cron (crond) 这个系统服务来控制任务 , Linux系统本来就有很多的计划任务需要启动 , 所以这个系统服务是默认开机启动的 。 Linux 为使用者提供的计划任务的命令就是 Crontab Crontab 是 Linux 下用来周…

Linux 网络编程详解一(IP套接字结构体、网络字节序,地址转换函数)

IPv4套接字地址结构 struct sockaddr_in {uint8_t sinlen;&#xff08;4个字节&#xff09;sa_family_t sin_family;&#xff08;4个字节&#xff09;in_port_t sin_port;&#xff08;2个字节&#xff09;struct in_addr sin_addr;&#xff08;4个字节&#xff09;char sin_zer…

地籍cad的lisp程序大集合_AutoCAD-LISP程序100例

{:soso_e179:}AutoCAD-LISP程序100例.JPG (143.82 KB, 下载次数: 28)2011-10-18 14:42 上传有说明很好&#xff01;顶如果您使用 AutoCAD,下面的内容对您一定有帮助。在某些方面能大大提高您的工作效率。下面的程序均以源程序方式给出&#xff0c;您可以使用、参考、修改它。bg…

javascript中数组的22种方法

前面的话数组总共有22种方法&#xff0c;本文将其分为对象继承方法、数组转换方法、栈和队列方法、数组排序方法、数组拼接方法、创建子数组方法、数组删改方法、数组位置方法、数组归并方法和数组迭代方法共10类来进行详细介绍对象继承方法数组是一种特殊的对象&#xff0c;继…

javascript/jquery高度宽度详情解说分析

为什么80%的码农都做不了架构师&#xff1f;>>> 一、window对象表示浏览器中打开的窗口 二、window对象可以省略 一、document对象是window对象的一部分 二、浏览器的HTML文档成为Document对象 window.location和document.location window对象的location属性引用的…

农用地包括哪些地类_土地地类一览表

一级类二级类三级类含义编号三大类名称编号名称编号名称1农用地指直接用于农业生产的土地&#xff0c;包括耕地&#xff0c;园地&#xff0c;林地&#xff0c;牧草地及其他的农业用地11耕地指种植农作物、土地&#xff0c;包括熟地、新开发复垦整理地&#xff0c;休闲地、轮歇地…

红黑树插入时的自平衡

红黑树插入时的自平衡 红黑树实质上是一棵自平衡的二叉查找树&#xff0c;引入带颜色的节点也是为了方便在进行插入或删除操作时&#xff0c;如果破坏了二叉查找树的平衡性能通过一系列变换保持平衡。 红黑树的性质 每个节点要么是红色&#xff0c;要么是黑色根节点必须是黑…

说一下自己对于 Linux 哲学的理解

查阅了一些资料&#xff0c;官方的哲学思想貌似是&#xff1a; 一切皆文件由众多单一目的的小程序&#xff0c;一个程序只实现一个功能&#xff0c;多个程序组合完成复杂任务文本文件保存配置信息尽量避免与用户交互什么&#xff0c;你问我的理解&#xff1f;哲学思想&#xff…

UWP学习记录

微软{X:Bind}、{Binding}资料网站 &#xff1a; https://msdn.microsoft.com/windows/uwp/xaml-platform/x-bind-markup-extension在View的ItemTemplate中绑定ViewModel的方法&#xff1a;1 <ItemsControl Name"XX" ItemsSource"{x:Bind VM.XXModels,ModeOne…

dw1000信标码_DW1000方案工牌型UWB标签,助力10厘米高精度室内定位!

DW1000方案工牌型UWB标签&#xff0c;助力10厘米高精度室内定位&#xff01;发布日期&#xff1a;2019-04-01 浏览次数&#xff1a;244次微能信息(95power)推出一款工牌型UWB标签VDU1510 &#xff0c;广泛应用于超宽带UWB定位系统&#xff0c;最高可实现10cm高精度人员定位。工…

【Java】HashMap源码(1.7)

Life is not a ridiculous number of life, the meaning of life lies in life itself HashMap源码 散列集 数组和链表可以保持元素插入的顺序&#xff0c;对数组来说&#xff0c;他的优点是拥有连续的存储空间&#xff0c;因此可以使用元素下标快速访问&#xff0c;但缺点在…

Docker 基本用法

1.安装&#xff1a; wget http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm rpm -ivh epel-release-6-8.noarch.rpm yum install docker-io -y2.获取镜像 pull docker pull ubuntu docker pull ubuntu:14.043.运行这个镜像&#xff0c;在其中运行bash应用…

画刷的使用

1.画刷的定义&#xff1a; HBRUSH hBrush; windows 自定义的画刷&#xff1a; WHITE_BRUSH、LTGRAY_BRUSH、GRAY_BRUSH、DKGRAY_BRUSH、BLACK_BRUSH和NULL_BRUSH &#xff08;也叫HOLLOW_BRUSH&#xff09; 获取方法如下&#xff1a; hBrush (HBRUSH) GetStockObject (GRAY_BR…

dataframe 控对象_iOS知识 - 常用小技巧大杂烩

1&#xff0c;打印View所有子视图po [[self view]recursiveDescription]2&#xff0c;layoutSubviews调用的调用时机* 当视图第一次显示的时候会被调用。* 添加子视图也会调用这个方法。* 当本视图的大小发生改变的时候是会调用的。* 当子视图的frame发生改变的时候是会调用的。…

【Java】jdk 1.8 新特性——Lambda表达式

Lambda表达式 jdk 1.8 新加入的特性&#xff0c;简化了简单接口的实现 函数式接口 函数式中只有一个待实现的方法&#xff0c;可以使用FunctionalInterface注解标注函数式接口.这个接口中只能有一个待实现的方法&#xff0c;但可以包含默认方法&#xff0c;静态方法以及Obje…

【Todo】Java8新特性学习

参考这篇文章吧&#xff1a; http://blog.csdn.net/vchen_hao/article/details/53301073 还有一个系列转载于:https://www.cnblogs.com/charlesblc/p/6123380.html

jsp调整字体大小font_html font标签如何设置字体大小?

首先我们先来看看htmlfont标签是如何来设置字体大小的&#xff1a;都只到htmlfont标签是个专门用来设置字体的标签&#xff0c;虽然在html5中用的会很少(因为都用css样式来设置font标签里面的属性)&#xff0c;但是个人觉得font标签还是相当强大的标签的&#xff0c;为什么这么…

runtime官方文档

OC是一种面向对象的动态语言&#xff0c;作为初学者可能大多数人对面向对象这个概念理解的比较深&#xff0c;而对OC是动态语言这一特性了解的比较少。那么什么是动态语言&#xff1f;动态语言就是在运行时来执行静态语言的编译链接的工作。这就要求除了编译器之外还要有一种运…