生成器有主要有四种方法:
-
next()
执行函数,直到遇到下一个yield为止,并返回值 -
send(value)
为生成器发送一个数值,next()方法就相当于send(None) -
close()
终止生成器 -
throw(exc[exc_value,[exc_tb]])
在生成器yield处引发一个异常,close()相当于引发一个GeneratorExit异常
输出型
一个斐波那契数列的例子
def fibonacci(): a, b = 0, 1 while True: yield b a, b = b, a+ba = fibonacci()for i in range(10): print a.next()
运行结果:
11235813213455python2.7 fb.py 0.01s user 0.01s system 94% cpu 0.025 total
生成器每次生成一个数字并返回。
接收输入型
def reciver(): while True: n = (yield) print "Got %s" % nr = reciver()r.next()r.send(1)r.send('2')
运行结果:
Got 1Got 2python2.7 rec.py 0.01s user 0.01s system 86% cpu 0.023 total
这个模型可以看做接收外部数据并进行处理。
输入输出型
生成器能否接收send传送来的数据,处理之后再返回呢?答案是肯定的
def get(): n = 0 result = None while True: n = (yield result) result = n*10t = get()t.next()for i in range(10): print t.send(str(i))t.close()
运行结果
0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999python2.7 problem.py 0.02s user 0.00s system 83% cpu 0.024 total
传递参数
当然生成器函数也是函数,也支持参数传递。
def countdown(n): print("counting down from %d" % n) while n > 0: yield n n -= 1 return c = countdown(10)print c.next()print c.next()for i in countdown(10): print iprint sum(countdown(10))
运行结果
counting down from 10109counting down from 1010987654321counting down from 1055
从上面的例子我们发现,每次调用生成器函数要先执行next()
函数,然后才能发送数据, 如果忘记的话就会报错。
TypeError: can't send non-None value to a just-started generator
这个有人容易忘记。这怎么办?用装饰器来自动执行:
def coroutine(func): def start(*args,**kwargs): g = func(*args,**kwargs) g.next() return g return start@coroutinedef reciver(): while True: n = (yield) print "Got %s" % nr = reciver()r.send(1)r.send('2')