首先,先看一个实例:
def generator(): print(123) content = yield 1 print('generatorNum',num) print(456) yield 2 #生成一个生成器 g = generator() #ret = g.send("函数") #调用send()函数取值,此时会报错,关于send()函数及报错的原因后面再说 #调用__next__()函数取值 ret = g.__next__() #结果为:输出123,ret或的值为1 #调用send()函数取值 ret = g.send("mmx") #结果为:输出generatorNum,mmx,456;ret获得的结果为2send()函数: 从上面可以看到send()函数也可以用来获取生成器中的值,并且用其获取生成器中值的效果和next基本一致,不同的地方在于用send()函数获取下一个值的时候,给上一yield的位置传递一个数据,这个数据即为传给send()函数的参数。 注意: 从上面很容易看出,第一次使用生成器的时候,必须要用__next__()获取下一个值,第二次获取值的时候才可以使用send()方法;并且最后一个yield不能接收外部的值,如果最后一个yield确实还需要实现一些功能,可以按如下的样式来写:
def generator(): 功能代码块 cont1 = yield 返回值 #第一个yield 功能代码块 cont2 = yield 返回值 #第二个yield 功能代码块 yield 返回值 #最后一个yield 功能代码块 yield #这里不加返回值即可1、这是一个求平均数的例子,其功能是:第一次调用时,求0的平均数,第二次调用传入一个值,求0和这个值的平均数,第三次同样传入一个数,求着三个数的平均数,…,依次类推。
def avger(): sum = 0 count = 0 avg = 0 while 1: num = yield avg sum += num count += 1 avg = sum/count g = avger() #生成生成器 ret = g.__next__() #求得0的平均数0 ret = g.send(20) #求的0与20的平均数 ret = g.send(30) #求得0、20与30的平均数2、带有装饰器的生成器示例——预激生成器 本例是对上一个例子的一个补充,在上例中,当生成器生成后,首次必须使用__next__()来进行一个初始化,然后才能用send传值,这里将用装饰器来装饰次函数,让第一次的__next__()自动执行。
#装饰器 def des(func): def inner(*args,**kwargs): g = func(*args,**kwargs) g.__next__() #自动调用__next__() return g return inner #生成器 @des def avger(): sum = 0 count = 0 avg = 0 while 1: num = yield avg sum += num count +=1 avg = sum/count #由于装饰器的作用,这次便可直接使用send()方法 g = avger() ret = g.send(20) ret = g.send(30) #此时ret的结果为25.0 ret = g.send(40) #此时ret的结果为(40+20+30)/3预激生成器 就是指的类似于本例中的这种生成器,不需要自己手动初始化,而使用装饰器来自动执行__next__()方法来激活。
这个关键字后面跟的是一个容器,此关键字可以将容器中的所有值挨个取出来,具体的将在实例中展开:
def generater(): a = 'abcd' b = '1234' yield from a#用在生成器当中,从容器a中返回一个一个的值, #后面只能跟一个值 yield from b #上面的代码等价于: def generater(): a = 'abcdc' b = '12345' for i in a: yield i for j in b: yield j