基础知识
yield和yield from的使用
yield可以理解为产生一个值,在函数里使用,会把该函数变成generator,它和return的区别在于,yield在返回值之后,代码段不会直接结束,而是中断,同时下一次调用(send()和next()方法)的时候会从这次中断的地方继续执行,即保留了上下文。
def test():
for i in range(3):
print(f'yield start')
yield i
print('end of yield')
a = test()
print(next(a))
print(next(a))
print(next(a))
b = test()
print(next(b))
# Output:
yield start
0
end of yield
yield start
1
end of yield
yield start
2
yield start
0
当next(a)超出生成器范围时,会报StopIteration异常。
def test():
for i in range(3):
yield i
a = test()
print(next(a))
print(next(a))
print(next(a))
# Output:
0
1
StopIteration异常
可以用for来避免该异常
def test():
for i in range(3):
yield i
a = test()
for i in a:
print(i)
# Output:
0
1
可以使用send()方法向generator中传值
def test():
a = 0
for i in range(3):
b = yield a
a = b + 1
gen = test()
print(gen)
print(next(gen)) # gen.send(None)等价于next(gen),这里必须先要第一次喂值
print(gen.send(1))
print(gen.send(10))
# Output:
0
2
11
查看生成器的状态
def simple_coro(a):
print('-> Started: a=',a)
b = yield a # 相当于是先返回a,暂停,直到next方法调用后,b赋值为send发送过来的数据,再执行到下一个yield暂停
print('-> Received: b =',b)
c = yield a+b # 先返回a+b,暂停,直到next方法调用后,c赋值为send发送过来的数据,再执行到下一个yield暂停
print('-> Received: c=',c)
my_coro2=simple_coro(14) # 实例化一个协程对象
from inspect import getgeneratorstate # 得到状态的函数
print(getgeneratorstate(my_coro2))
next(my_coro2)
print(getgeneratorstate(my_coro2))
my_coro2.send(28)
my_coro2.send(99)
# Outputs:
GEN_CREATED
-> Started: a= 14
GEN_SUSPENDED
-> Received: b = 28
-> Received: c= 99