Python基础:14生成器
yield表达式只用于定义生成器函数,且只能存在于函数的定义体中。只要一个函数内部使用了yield表达式,则该函数就成为生成器函数。
当调用生成器函数时,它返回一个称为生成器的迭代器。然后该生成器控制生成器函数的执行。当调用生成器的其中一个方法时,执行开始。此时,执行会行进到第一个yield表达式,在那里执行被挂起并返回一个值给生成器的调用者。挂起的意思是保存所有的局部状态,包括当前局部变量的绑定、指令的指针和内部的计算栈。当通过调用生成器的一个方法来恢复执行时,函数可以准确地继续执行,就好像yield表达式只是一个外部的调用。恢复执行后yield表达式的值取决于恢复执行的方法。
所有这些使得生成器函数与协程非常类似;它们可以yield多次,它们有多个入口点且它们的执行可以挂起。唯一的区别是生成器函数不可以控制yield之后执行应该从何处继续;控制始终被转让给生成器的调用者。
生成器函数,要么没有return语句,要么带有空的return语句,否则,会引起语法错误。
调用生成器,当到达一个真正的返回或者函数没有更多的值返回时,一个StopIteration 异常就会抛出。简单例子如下:
def simpleGen():
yield 1
yield '2 -->punch!'
return
yield 4 >>>myG = simpleGen()
>>>myG.next()
1
>>>myG.next()
'2 -->punch!'
>>>myG.next()
Traceback (mostrecent call last):
File"", line 1, in ?
StopIteration
生成器迭代器的方法。它们可用于控制生成器函数的执行。注意当生成器已经在执行时,调用下面的任何一个生成器方法都将引发ValueError异常。
1:generator.next()
开始生成器函数的执行或者在上一次执行的yield表达式之后恢复执行。然后执行继续行进到下一个yield表达式,在那里生成器被再次挂起并返回值给next()的调用者。当生成器函数使用next()方法恢复执行时,当前的yield表达式的值始终是None。如果生成器退出时没有yield另外一个值,则引发一个StopIteration异常。比如下面的代码:
def gen():
while True:
print 'before yield'
res = yield random.randint(1, 100)
print 'res is ', res >>> ag = gen()
>>> ag
<generator object gen at 0x0000000002645168> >>> ag.next()
before yield
12
>>> ag.next()
res is None
before yield
14
2:generator.send(value)
开始生成器函数的执行或者在上一次执行的yield表达式之后恢复执行,并“发送”一个值value到生成器中,该value参数成为当前yield表达式的结果。send()方法返回生成器yield的下一个值,如果生成器退出时没有yield另外一个值则引发StopIteration。 当调用send()用于开始生成器的执行时,它必须以None作为参数进行调用,因为没有接受该值的yield表达式。
>>> ag2 = gen()
>>> ag2
<generator object gen at 0x00000000026451F8>
>>> ag2.send(None)
before yield
28
>>> ag2.send(1)
res is 1
before yield
61
>>> ag2.send('hehe')
res is hehe
before yield
21
>>> ag2.next()
res is None
before yield
22
>>> ag3 = gen()
>>> ag3.send(1)
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
TypeError: can't send non-None value to ajust-started generator
3:generator.throw(type[, value[, traceback]])
在生成器暂停的地方引发一个type类型的异常,并返回生成器函数yield的下一个值。如果生成器在退出时没有yield一个值,则引发StopIteration异常。如果生成器函数没有捕获传递进来的异常或者引发一个不同的异常,那么该异常将传播到调用者。例子如下:
def gen():
while True:
print 'before yield'
try:
res = yield random.randint(1,100)
except Exception ,e:
print 'recv except: ', e
print 'res is ', res >>> ag = gen()
>>> ag.next()
before yield
68
>>> ag.next()
res is None
before yield
48
>>> ag.throw(TypeError, 1)
recv except: 1
res is None
before yield
37 >>> ag.throw(KeyboardInterrupt, 1)
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
File"test.py", line 7, in gen
res =yield random.randint(1,100)
KeyboardInterrupt: 1
>>> ag.next()
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
StopIteration
4:generator.close()
在生成器函数暂停的地方引发一个GeneratorExit。如果生成器函数此后引发StopIteration(正常退出或者由于已经正在关闭),或者没有捕获GeneratorExit异常,close会返回到调用者。否则,如果生成器yield一个值,则引发一个RuntimeError。如果生成器引发其它任何异常,它会被传播到调用者。如果生成器已经由于异常退出或正常退出,close()不会做任何事情。
def gen():
while True:
print 'before yield'
try:
res = yield random.randint(1,100)
except Exception ,e:
print 'recv except: ', e
print 'res is ', res >>> ag2 = gen()
>>> ag2.close()
>>> ag2.send(2)
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
StopIteration
>>> ag2.next()
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
StopIteration def gen():
while True:
print 'before yield'
try:
res = yield random.randint(1,100)
except Exception ,e:
print 'recv except: ', e
except GeneratorExit, e:
print 'recv exit: ', e
print 'res is ', res >>> ag = gen()
>>> ag.next()
before yield
4
>>> ag.next()
res is None
before yield
16
>>>ag.close()
recv exit:
res is None
before yield
Traceback(most recent call last):
File "<stdin>", line 1, in<module>
RuntimeError:generator ignored GeneratorExit
可以在PEP 的255 和342 中,以及给读者介绍python2.2 中新特性的linux 期刊文章中阅读到更多关于生成器的资料:http://www.linuxjournal.com/article/5597
参考:
http://python.usyiyi.cn/python_278/reference/expressions.html#yieldexpr
https://docs.python.org/2/reference/expressions.html#yieldexpr
http://www.cnblogs.com/huxi/archive/2011/07/14/2106863.html
http://pyzh.readthedocs.org/en/latest/the-python-yield-keyword-explained.html
Python基础:14生成器的更多相关文章
- python基础(14):生成器、列表推导式
1. 生成器 什么是⽣成器?⽣成器实质就是迭代器. 在python中有三种⽅式来获取⽣成器: 1. 通过⽣成器函数 2. 通过各种推导式来实现⽣成器 3. 通过数据的转换也可以获取⽣成器 ⾸先,我们先 ...
- 十四. Python基础(14)--递归
十四. Python基础(14)--递归 1 ● 递归(recursion) 概念: recursive functions-functions that call themselves either ...
- 十三. Python基础(13)--生成器进阶
十三. Python基础(13)--生成器进阶 1 ● send()方法 generator.send(value) Resumes the execution, and "sends&qu ...
- 十二. Python基础(12)--生成器
十二. Python基础(12)--生成器 1 ● 可迭代对象(iterable) An object capable of returning its members one at a time. ...
- python基础(14)-反射&类的内置函数
反射 几个反射相关的函数可参考python基础(10)-匿名函数&内置函数中2.2.4反射相关 类的一些内置函数 __str__()&__repr__() 重写__str__()函数类 ...
- (转)python基础学习-----生成器和迭代器
在Python中,很多对象都是可以通过for语句来直接遍历的,例如list.string.dict等等,这些对象都可以被称为可迭代对象.至于说哪些对象是可以被迭代访问的,就要了解一下迭代器相关的知识了 ...
- Python基础(生成器)
二.生成器(可以看做是一种数据类型) 描述: 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我 ...
- Python基础-迭代器&生成器&装饰器
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...
- python基础——14(shelve/shutil/random/logging模块/标准流)
一.标准流 1.1.标准输入流 res = sys.stdin.read(3) 可以设置读取的字节数 print(res) res = sys.stdin.readline() print(res) ...
- Python基础之生成器、迭代器
一.字符串格式化进阶 Python的字符串格式化有两种方式: 百分号方式.format方式,由于百分号的方式相对来说比较老,在社区里讨论format方式有望取代百分号方式,下面我们分别介绍一下这两种方 ...
随机推荐
- HDU2056
/* * 指数型母函数 */ #include<cstdio> #define mod 100 typedef long long LL;//杭电需用int64 int powerMo ...
- WPF学习笔记-用Expression Blend制作自定义按钮
1.从Blend工具箱中添加一个Button,按住shift,将尺寸调整为125*125; 2.右键点击此按钮,选择Edit control parts(template)>Edit a cop ...
- 集训队日常训练20180518-DIV2
A.3232 n个物品,换取要花积分,问刚好花完积分能换最大多少价值的物品. 多重背包. #include <bits/stdc++.h> using namespace std; ]; ...
- c++的引用用法
一.引用简介 引用就是某一变量(目标)的一个别名,对引用的操作与对变量的直接操作完全一样. 引用的声明方法:类别标识符&引用名=目标变量名: 例1: int a; int &ra=a; ...
- R语言可视化--qplot函数
ggplot绘图系统 使用动词名词形容词构造句子的过程,将数据映射到美学属性上的过程,由层组成 绘图函数 qplot() :参数包括美学属性.几何体.面.统计.坐标系.主题这些层次. ggplot() ...
- 模拟3题解 T3建造游乐园
T3建造游乐园 这题的关键是推式子 i个点中,有g[i]个方案是度为偶数但不一定连通那么就要减去不合法的设已有j个合法,其个数为f[j],剩下i-j个的方案数是g[i-j]选出来一个固定的点在合法的j ...
- 二分查找(BinSearch)的Javascript实现
二分查找 解析:二分查找,也为折半查找.对于一个从小到大排列的有序数组,首先要找到一个中间值,通过与中间值比较,大的放又,小的放在左边.再在两边中寻找中间值,持续以上操作,直到找到所在位置为止. 1. ...
- 2017年Android SDK下载安装及配置教程(附带原文地址)
首先声明: Unity版本5.6.3f1 最近试着在Unity中利用高通做AR开发时,发布项目文件需要发布到Android平台,遇到一些问题,看了网上的一些资料,踩了一些坑,现在总结出来,希望有相同的 ...
- 学习JDK1.8集合源码之--TreeSet
1. TreeSet简介 TreeSet是Set的实现类之一,是不可重复集合,非线程安全的. TreeSet是SortedSet的唯一实现类,实现了元素的自动排序,排序不是以插入的顺序排序,而是默认以 ...
- 使用 javascript 替换 jQuery
使用 javascript 替换 jQuery jQuery 曾风靡一个时代,大大降低了前端开发的门槛,丰富的插件也是前端开发者得心应手的武器库,但是,这个时代终于要落幕了.随着 JS 标准和浏览器的 ...