如果不激活协程,那么协程没什么用,调用averager().send(x)之前一定要调用next(averager())来激活,为了简化协程用法,有时候会使用预激装饰器:
import functools
# 定义预激装饰器
def coroutine(func):
"""装饰器函数"""
# @functools.wraps(func)
def primer(*args,**kwargs):
gen = func(*args,**kwargs)
next(gen)
return gen
return primer
@coroutine
def averager():
"""我是被装饰函数"""
total = 0.0
count = 0
average =1
while True:
term = yield average
total += term
count += 1
average = total/count
print(average)
# print(averager.__name__,averager.__doc__)
av = averager() #下面就不用调用next了,因为av接收到的就是被激活后的函数gen的地址
av.send(10)
av.send(3)
print(averager.__name__)
注意:函数名打出来的是primer不是averager,这就是说,被装饰器装饰后的函数,函数名都会变成装饰器的内部函数名。
一般定义装饰器的话可以不用考虑这点,但是如果多个函数被两个装饰器装饰时就报错,因为两个函数名一样,第二个函数再去装饰的话就报错.
解决方案就是引入 functools.wraps
输出