yield 生成器, 当函数中有yield, 那么这个函数编程生成器, 对其进行函数调用, 不会执行, 会返回一个生成器对象
In [1]: def createNum():
...: print("__start__")
...: a, b = 0, 1
...: for i in range(5):
...: print("__1__")
...: yield b
...: print("__2__")
...: a, b = b, a+b
...: print("__3__")
...: print("__stop__")
...:
In [3]: a
Out[3]: <generator object createNum at 0x000001FEF6C8AB48>
In [5]: type(a)
Out[5]: generator
生成器对象使用next()开始执行
In [4]: next(a)
__start__
__1__
Out[4]: 1
可见, 一次next()
调用, 程序从上往下执行, 恰好到yield b
处停止, 并返回yield
后面变量的值1
进行下一次next()
调用
In [6]: next(a)
__2__
__3__
__1__
Out[6]: 1
程序从上一次next()
执行的位置继续向下执行, 直到下一次遇到yield b
通过for执行, 不会出现StopIteration
错误
In [7]: for each in a:
...: print(each)
...:
__2__
__3__
__1__
2
__2__
__3__
__1__
3
__2__
__3__
__1__
5
__2__
__3__
__stop__
In [1]: def test():
...: i = 0
...: while i < 5:
...: temp = yield i
...: print(temp)
...: i += 1
...:
试想, temp
的值是否是yield
后面i
的值
In [4]: t.__next__()
Out[4]: 0
第一次执行, 到yield
停止, 返回i
的值
In [5]: t.__next__()
None
Out[5]: 1
第二次执行, 到yield
停止, 期间打印None
, 最后返回i
的值, 可见, 其并未如我们预期所想, yield i
整体没有任何值, 那么如何才能实现给temp
赋值的效果呢?
In [6]: t.send('send')
send
Out[6]: 2
发现, send()
和next()
都可以让生成器向下执行, 不同的是, send(arg)
通过一个参数, 给yield i
整体赋值
需要注意的是, 在生成器的第一次使用时, 由于程序并未执行到
yield
, 所以此时通过send()
函数传参调用生成器会报错TypeError: can't send non-None value to a just-started generator
, 但是可以传入参数None
来使生成器走到yield
处
协程简单实现
In [25]: def test1():
...: while True:
...: print('__1__')
...: yield None
...:
In [26]: def test2():
...: while True:
...: print('__2__')
...: yield None
...:
In [27]: t1 = test1()
In [28]: t2 = test2()
In [29]: import time
In [30]: while True:
...: t1.__next__()
...: t2.__next__()
...: time.sleep(1)
...:
__1__
__2__
__1__
__2__
__1__
__2__
__1__
__2__
__1__
__2__
__1__
__2__
__1__
__2__
通过生成器的中断特性以及next()
的执行, 实现程序间的跳转, 完成简单协程