生成器扩展知识
前面说过函数内只要有yield关键字,那么该函数的执行结果就是一个生成器。生成器本身也是一个迭代器对象,可以使用next()方法去取值,还有一个格式可以支持send()去传值给yield并执行next()。
def foo():
while True:
x = yield 'aaa'
print('value:',x)
g=foo()
print(g)
print(g.send(None)) #第一次必须要next()触发,这里使用send(None)和next(等价)
print(g.send(2)) #send传值给yield并执行next()
#执行结果:
<generator object foo at 0x000001D39EC61DB0>
aaa
value: 2
aaa
总结
-
要使用send方法传值并触发生成器必须至少next()一次,或者send(None)一次,不然会报错:TypeError: can't send non-None value to a just-started generator
-
send(2)的作用就是先执行传值,将2传给yield,然后执行next()
加装饰器实现先next()一次生成器
def deco(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
next(res)
return(res)
return wrapper
@deco
def foo():
print('starting ...')
while True:
x = yield 'aaa'
print('value:', x)
g = foo()
print(g.send(2))
#执行结果
starting ... #g = foo()执行结果
value: 2
aaa
与其它函数协同工作
def deco(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
next(res)
return(res)
return wrapper
list_eat = []
@deco
def foo(name):
print('starting ...')
while True:
food = yield list_eat #yield接受send过来的值,传给food
list_eat.append(food)
print('%s eat %s' %(name,food))
def make_egg(people,num):
for i in range(1,num):
people.send('egg%s' %i) #发送给people,peopl必须是一个生成器
g = foo('jack')
make_egg(g,5)
#执行结果:
starting ...
jack eat egg1
jack eat egg2
jack eat egg3
jack eat egg4
多个函数通过生成器协同
两个函数间传值,接受值格式:
def deco(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
next(res)
return res
return wrapper
@deco
def foo1():
while True:
x1 = yield #yield接受值,可以是其它函数传值过来
print(x1)
def foo2(target): #target传入foo1
target.send(值)
三个或三个以上类似:
def deco(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
next(res)
return res
return wrapper
@deco
def foo1():
while True:
x1 = yield #yield接受值,可以是其它函数传值过来
print(x1)
@deco
def foo2(target):
while True:
x2 = yield
target.send(x2)
def foo3(target):
target.send(值)