参考自
任何使用yield的函数都称之为生成器,生成器这个概念就不多说了。
例子
例子1 * 计数器
def count(n):
while n > 0:
# 迭代器返回n
yield n
# 下一次迭代器开始的地方
n -= 1
for i in count(5):
print(i)
例子2 * 斐波拉契数列
def fibonacci():
a = b = 1
# 第一次迭代器返回a,即1
yield a
# 第二次迭代器返回b,即1
yield b
while True:
a, b = b, a+b
# 第i次地带返回b (i >= 3)
yield b
for num in fibonacci():
# 如果没有下述跳出循环的代码,回陷入死循环,一直打印斐波拉契数
if num > 100:
break
print(num)
例子3 * 生成器实际上调用的是.__next__()
>>> def aboutYield():
... print('first')
... yield 5 # I
... print('second')
... yield 23 # II
... print('third')
...
>>> g = aboutYield()
>>> g.__next__() # 第一次进入,到I返回5结束
first
5
>>> g.__next__() # 第二次进入,到II返回23结束
second
23
>>> g.__next__() # 第三次进入,但找不到yield代表的返回句子,报错
third
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
return 的作用,中止生成器
>>> def aboutYield():
... print('first')
... yield 5
... print('second')
... return
... yield 23
...
>>> g = aboutYield()
>>> g.__next__()
first
5
>>> g.__next__() #执行遇到return,直接终止
second
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
例子4 * .send(<message>)
向生成器传送信息
.send(<message>)
实质上与.__next__()
是相似的,区别是send是传递yield表达式的值进去,而next不能传递特定的值,只能传递None进去。
因此可以认为g.next()和g.send(None)是相同的。
>>> def haveFun():
... print('start')
... # 第一次进入生成器返回1
... # 第二次进入生成器,让输入值'hello'赋予给m
... m = yield 1
... print(m)
... print('middle')
... # 第二次进入生成器返回2
... # 第三次进入生成器,让输入值'world'赋予给m
... m = yield 2
... print(m)
... print('end')
...
>>> g = haveFun()
>>> g.send(None)
start
1
>>> g.send('hello')
hello
middle
2
>>> g.send('world')
world
end
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
```
## 例子5 * 用yield实现协程,生产者消费者
```python
def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK'
def produce(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close()
c = consumer()
produce(c)
```
![在这里插入图片描述](https://img-blog.csdn.net/20160704123959072)