python 生成器、列表解析式、yield、迭代器

我们习惯生成列表通过list = [1, 2, 3]的方式。还有一种很方便的列表生成方式
list = [a*2 for a in range(10)],或者list = [fun(a) for a in range(10)]都是可以的
>>> L1 = [a*2 for a in range(10)]
>>> L1
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
如果只是生成一个100元素,1000元素的列表,那很简单,可是你需要一个100万,一亿个元素的列表时,这样去生成列表,你要知道,它是实实在在的存在你的内存里面,这么大一个列表,过于耗费内存。
那么有没有什么好的解决办法呢?------------>生成器
按照某种算法推算出列表元素,可以一直一边循环一边计算出列表元素的机制,称之为生成器:generator。一个简单生成器构造:列表是L = [a*2 for a in range(10)] 生成器把中括号[]换成小括号()就好了,G = (a*2 for a in range(10)) 这样就得到了一个生成器,[.....]生成列表,(.....)生成生成器
>>> g = (a*a for a in range(10))
>>> g
<generator object <genexpr> at 0x0000001D925F3308> #1
>>> for v in g: #2
... print(v)
1
4
9
16
25
36
49
64
81
在#1处我们生成了一个generator obj ,通过#2 的方式就可以取到当中的元素了。
首先我们来写一个斐波拉契数列 1, 1, 2, 3, 5, 8, 13, 21.....除第一个数外,每前两个数的和等于第三个数
fib_list = []
def fib(n):
i, a, b = 0, 0, 1
while i < n:
fib_list.append(b)
a, b = b, a+b
i = i + 1
f = fib(6)
print(fib_list)
#结果为
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
这样就得到了一个简单斐波拉契数列了。
当然我们还可以用yield来进行改装,把它变成一个生成器对象,yield: 在函数执行时会给函数返回generator对象,可以通过该对象的obj.next()方法或next(obj)来启动函数
>>> def generator_example():
... print('before yield')
... yield 'first yield'
... print('after first yield')
... message = yield 'second yield' #1 调用obj.send('message')可把值赋给yield表达式,同时返回yield右边的内容
... print('第二个yield收到send函数的消息:{}'.format(message))
... yield
... return 'over'
>>> g = generator_example() #2 运行带yield的函数,返回一个generator obj
>>> g
<generator object generator_example at 0x0000006E725E3308>
>>> res = g.__next__() #3 调用obj.__next__()方法启动generator
before yield
>>> print(res)
first yield
>>> res2 = next(g) #4 next(obj) 等同于obj.__next__()
after first yield
>>> print(res2)
second yield
>>> res3 = g.send('form send: after second yield')
第二个yield收到send函数的消息:form send: after second yield
>>> print(res3)
None
>>> try:
... next(g)
... print('上一个next(g)因为没有yield,所以触发错误,这儿不会执行')
... except StopIteration as e:
... print(e.value)
over
上面没有提到obj.send()方法,#3处第一次通过obj.next()方法启动generator后,函数返回第一个yield右边的值,并停在了哪儿,然后第二次通过next(obj)让函数继续运行到第二个yield,返回second yield然后停住,然后第三次通过obj.send(value)的方法把value传给给了暂停地方的yield表达式的 message,并启动函数继续运行直到遇到下一个yield。......最后当触发最后次yield但是后面没有yield能暂停就报错了,使用try:抓住错误,并接受函数返回值over
yield来实现斐波拉契数列
def fib(n):
i, a, b = 0, 0, 1
while i < n:
yield b #在这儿用yield就好了
a, b = b, a+b
i = i + 1
return '--done--'
f = fib(6)
while True:
try:
res = next(f)
print(res)
except StopIteration as e:
print(e.value)
break
#运行结果为
1
1
2
3
5
--done--
生成器都是迭代器
还有可以作用于for循环的数据类型有:
一类是集合数据类型:如 list、tuple、duct、str等
另一类是generator包括生成器,和带yield的generator function,这些可以直接作用于for循环的对象统称为可迭代对象(Iterable)可使用isinstance()来判断是否为Iterable
>>> from collection import Iterable
>>> isinstance([], Iterable)
True
而生成器不但可以作用于for循环,还能被next()函数不断调用返回下一个值,直到抛出StopIteration错误无法继续
可以被next()函数调用并不断返回下一个值的对象就称为迭代器Iterator
list、idct、str虽然可以用for循环,可迭代,但是没有nex()方法就不是Iterator迭代器
而使用iter()函数就可以把它们变成迭代器了
>>> gen_list = iter([1, 3, 5, 7])
>>> gen_list
<list_iterator object at 0x00000052371B6C50>
range() 或for line in f:这样的内部也都是封装了迭代器
python 生成器、列表解析式、yield、迭代器的更多相关文章
- [转]Python 的列表解析式,集合解析式,字典解析式
Python 的列表解析式,集合解析式,字典解析式 这三种都是 python 里面的语法糖. 语法糖,Syntactic Sugar,就是为了写程序时候少出错,发明的一些简便的方法,但不影响这个语法的 ...
- python之列表推导、迭代器、生成器
http://blog.chinaunix.net/uid-26722078-id-3484197.html 1.列表推导 看几个例子,一切就明白了. #!/usr/bin/python number ...
- Python 生成器的使用(yield)
一. 生成器就是一个特殊的迭代器, 使用关键字yield就可以生成一个生成器 def func(): for i in range(10): yield i item = func() yield i ...
- Python之路(第十篇)迭代器协议、for循环机制、三元运算、列表解析式、生成器
一.迭代器协议 a迭代的含义 迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 b为何要有迭代器? 对于序列类型:字符串.列表 ...
- Python之路迭代器协议、for循环机制、三元运算、列表解析式、生成器
Python之路迭代器协议.for循环机制.三元运算.列表解析式.生成器 一.迭代器协议 a迭代的含义 迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的 ...
- Python之列表生成式、生成器、可迭代对象与迭代器
本节内容 语法糖的概念 列表生成式 生成器(Generator) 可迭代对象(Iterable) 迭代器(Iterator) Iterable.Iterator与Generator之间的关系 一.语法 ...
- python列表解析式,字典解析式,集合解析式和生成器
一.列表解析式(列表推倒式): 功能:是提供一种方便的列表创建方法,所以,列表解析式返回的是一个列表. 1 lst = [1, 3, 5, 8, 10] 2 ll = [x+x for x in ls ...
- Python函数——列表推导式、生成器与迭代器
列表推导式 产生背景 现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求你把列表里的每个值加1,你怎么实现? 第一种方法: a = [1,3,4,6,7,7,8,9 ...
- 【转】Python之列表生成式、生成器、可迭代对象与迭代器
[转]Python之列表生成式.生成器.可迭代对象与迭代器 本节内容 语法糖的概念 列表生成式 生成器(Generator) 可迭代对象(Iterable) 迭代器(Iterator) Iterabl ...
随机推荐
- 如何自定义FusionCharts图表上的工具提示?
中的工具提示是什么?当鼠标悬停在一个特定的数据点上时就会显示工具提示,提示以下信息: 单系列图表(饼图和圆环除外):名称及数值 Pie & Doughnut:名称及数值/百分比 多系列组合图表 ...
- 深入理解Intent和IntentFiler(一)
http://blog.csdn.net/u012637501/article/details/41080891 为了比较深刻的理解并灵活使用Intent,我计划将这部分的学习分为两步:一是深入理解I ...
- 字典树模板题(统计难题 HDU - 1251)
https://vjudge.net/problem/HDU-1251 标准的字典树模板题: 也注意一下输入方法: #include<iostream> #include<cstdi ...
- P2430 严酷的训练 题解
题目背景 Lj的朋友WKY是一名神奇的少年,在同龄人之中有着极高的地位... 题目描述 他的老师老王对他的程序水平赞叹不已,于是下决心培养这名小子. 老王的训练方式很奇怪,他会一口气让WKY做很多道题 ...
- 简单使用metamascara
package.json 配置文件信息 { "name": "test-mascara", "version": "1.0.0&q ...
- 20175310 《Java程序设计》第1周学习总结(1)安装虚拟机
20175310 <Java程序设计>第1周学习总结(1)安装虚拟机 开学前老师在蓝墨云班课上上传了预备作业,其中有一个就是安装Linux操作系统,参考了<>,下载安装Virt ...
- Linux 局域网同步时间
选择一台能上外网的机器作为时间服务器(都不能上亦可以,任选一台即可,但是只能保证局域网内时间同步) 配置此时间服务器 安装 ntp 在 /etc/ntp.conf 中配置 restrict 127.0 ...
- proxy config (firefox config)
sudo apt-get install shadowsocks sudo apt-get install polipo 编辑polipo config: sudo vim /etc/polipo/c ...
- 人生苦短之学习Python50本书籍(包涵基础、算法、机器学习、模块、爬虫框架、树莓派等)总有你想要的书籍
很多小伙伴说想学习想学习但是没有学习书籍,我给大家分享一大波学习书籍,具体的可以自己往下翻 <"笨办法学"Python3> Zed Shaw 著 (2018年5月) ...
- 解密:Python风靡全宇宙,首要原因竟是它?
就让我们从近年来大数据的兴起说起,为你娓娓道来Python火爆的真正原因. 郁闷的大数据程序员 随着大数据的崛起,大多数行业发现自己进入了一种恐慌状态:他们花费了大量的时间和金钱来建立他们的大数据渠道 ...