通过示例学习python生成器。
![](https://i-blog.csdnimg.cn/blog_migrate/356686d1d9af4d02e771652d54d2c305.png)
作为迭代器
使用生成器(生成器功能)
>>> def integers():
i = 1
while True:
yield i
i = i + 1
>>> a = integers()
>>> next(a)
1
>>> next(a)
2
>>> next(a)
3
>>> next(a)
4
>>> next(a)
5
>>>
将生成器分配给变量将自动创建.__ next __()或next(generator)方法
这将允许您遍历生成器值
转换为清单
>>> def yrange(n):
i = 0
while i < n:
yield i
i += 1
>>> y = yrange(5)
>>> list(y)
[0, 1, 2, 3, 4]
>>> list(y)
[]
您可以将生成器转换为列表,但是在该过程中它将丢失其值并将其传输到列表。
>> y = yrange(5)
>>> ylist = list(y)
>>> ylist
[0, 1, 2, 3, 4]
>>> ylist
[0, 1, 2, 3, 4]
>>> list(y)
[]
您可以将其分配给变量以保留列表。 请记住,原始生成器将消失。
发送给发电机的功率
>>> def whizbang():
for i in range(10):
x = yield i
print('i got {}'.format(x))
>>> bangbang = whizbang()
>>> bangbang.__next__()
0
>>> next(bangbang)
i got None
1
>>> bangbang.__next__()
i got None
2
>>> next(bangbang)
i got None
3
>>> bangbang.__next__()
i got None
4
next(generator)与generator .__ next__ ()相同。 类似于vars(class)与class .__ dict__相同。
>>> next(bangbang)
i got None
5
让我们开始发送东西。 生成器具有generator.send()方法。
>>> bangbang.send('yo')
i got yo
6
>>> bangbang.send('yo yo yo')
i got yo yo yo
7
在这种情况下,bangbang.send的参数分配给x。 由于x = yield i,意味着x = yield发送值和yield i
>>> list(bangbang)
i got None
i got None
i got None
[8, 9]
转换为列表不适用于.send()
>>> bangbang = whizbang()
>>> next(bangbang)
0
>>> list(bangbang.send('test'))
i got test
Exception: TypeError: 'int' object is not iterable
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-1-5e0978d85904> in <module>()
----> 1 list(bangbang.send('test'))
TypeError: 'int' object is not iterable>>>
您需要至少一次调用next(generator)才能执行generator.send()
>>> bangbang = whizbang()
>>> bangbang.send('s')
Exception: TypeError: can't send non-None value to a just-started generator
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-1-10a417413dc0> in <module>()
----> 1 bangbang.send('s')
TypeError: can't send non-None value to a just-started generator
尽早删除生成器上的值
清理生成器内部的值很有用。 例如,如果您的应用程序遇到未知错误并且使您的应用程序处于脏状态,而不必冒写入错误数据的风险,则可以提早关闭生成器。
>>> bangbang = whizbang()
>>> bangbang
<generator object whizbang at 0x7f6b1537b288>
>>> bangbang.__next__
<method-wrapper '__next__' of generator object at 0x7f6b1537b288>
>>> bangbang.__next__()
0
>>> bangbang.__next__()
i got None
1>>> bangbang.__next__()
i got None
2>>> bangbang.__next__()
i got None
3>>> bangbang.__next__()
i got None
4>>> bangbang.close()
>>> bangbang.__next__()
Exception: StopIteration:
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-1-6f12368577ae> in <module>()
----> 1 bangbang.__next__()
StopIteration:
正如您在上方看到的,bangbang应该迭代到10,但是由于我们调用bangbang.close()而在4处停止
进一步阅读
- http://anandology.com/python-practice-book/iterators.html
- https://jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/
- https://stackoverflow.com/questions/10695456/what-is-the-result-of-a-yield-expression-in-python