本篇将介绍 python 生成器,更多内容请参考: python 学习指南
前言
通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含 100 万个元素的列表,不仅占用很大的存储空间,如果我们仅仅访问前面几个元素,那后面绝大多数占用的空间都白白浪费了.
python 生成器是用来代替 "不一定能够使用全部元素的数组", 等到使用某一元素时, 才生成该元素, 用来节省空间.
生成器创建方式
第一种:
在前面我们介绍 python 列表生成式,这里我们只需要把列表生成式的 [] 改成(), 就创建了一个 generatro
创建 L 和 g 的区别仅在于最外层的 [] 和(),L 是一个 list, 而 g 是一个 generator
>>>L = [x * x for x in range(10)]
>>>L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>>g = (x*x for x in range(10))
>>>g
<generator object <genexpr> at 0x1022ef630>
上面表达式中我们可以直接列出 list(L) 的每一个元素,但我们打印 g 的时候,却打印了 g 的类型,那么,我们如何打印 generator 的每一个元素呢?
如果要一个一个打印出来,可以通过 next() 函数获得 generator 的下一个返回值:
generator 保存的是算法,每次调用 next(g), 就计算出 g 的下一个元素的值,知道计算出最后一个元素,没有更多元素时,抛出 StopIteration 的错误.
>>>next(g)
0
>>>next(g)
1
>>>next(g)
4
>>>next(g)
9
>>>next(g)
16
>>>next(g)
25
>>>next(g)
36
>>>next(g)
49
>>>next(g)
64
>>>next(g)
81
>>>next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
这样不断调用 next(g) 实在是太变态了,生成器是可迭代对象
这样,知道用什么来了吧?
>>>from collections import Iterable #载入模块
>>>isinstance(g, Iterable) #生成器是可迭代对象吗?
True
当然是使用强大的 for...in 迭代来实现
通过 for 迭代的方式来循环生成器,并不用关心 StopIteration 的错误.
>>>g = (x * x for x in range(10))
>>>for n in g:
print(n)
0
1
4
9
16
25
36
49
64
81
使用关键字 yield 关键字
generator 非常强大.如果推算的算法比较复杂,用类似列表生成式的 for 循环无法实现的时候,还可以用函数来实现
斐波那契数列生成器
输出结果: (执行完毕不会崩溃)
def creatNum():
print("---开始执行生成器方法---")
a,b = 0,1
for i in range(0,5):
print("--step1--")
yield b
print("--step2--")
a,b = b,a+b
print("--step3--")
print("--stop--")
print("直接调用方法...")
print(creatNum())
#这里用一个标识符来指向生成器(不要把creatNum()当做函数)
func = creatNum()
#使用for循环来执行生成器
for i in func:
print(i)
---开始执行生成器方法---
#直接调用方法...
<generator object creatNum at 0x101c30f10>
在执行生成器时, 可以使用 生成器. send(param) 方法
--step1--
1
--step2--
--step3--
--step1--
1
--step2--
--step3--
--step1--
2
--step2--
--step3--
--step1--
3
--step2--
--step3--
--step1--
5
--step2--
--step3--
--stop--
send 方法不光是执行一步 next 操作, 还会把 send 里面的参数传到生成器中充当 yield 表达式的返回值
输出结果: (可见next输出temp为none , 而send 则把值传递进了生成器)
def test():
i = 0
while i < 5:
temp = yield i
print(temp)
i += 1
t = test()
#先使用next执行,看能出来什么结果
t.__next__()
t.__next__()
print(t.__next__())
#使用send执行
t.send("1231231231223123")
print(t.send("hahahahhahaha"))
参考
None
None
2
1231231231223123
hahahahhahaha
4
python 生成器是怎样工作的
Python 中的 yield 关键字
python 生成器
廖雪峰 - 生成器
来源: https://www.cnblogs.com/miqi1992/p/8302597.html