Python生成器函数
生成器
生成器指的是生成器对象,可以由生成器表达式生成,也可以使用yield关键字编写一个生成器函数,调用这个函数得到一个生成器对象。
生成器对象是一个可迭代对象,是一个迭代器
生成器对象是延时计算,惰性求值的对象
m = (i for i in range(10)) type(m)m (generator, <generator object <genexpr> at 0x000001AFE65720A0>)
生成器函数
函数体中包含yield关键字的函数,就是生成器函数,调用后返回生成器对象
def g(): for i in range(10): yield i f = g() type(f),f (generator, <generator object g at 0x000001AFE65721A8>)
可使用next(f)驱动
普通函数调用,函数会立即执行,直到执行结束,生成器函数调用,并不会立即执行函数体,而是返回一个生成器对象,需要使用next()内嵌函数来驱动这个生成器对象
生成器表达式和生成器函数都可以得到一个生成器对象,只不过生成器函数可以写的更加的复杂。
生成器函数的执行
def foo(): print(1) yield 2 #暂停当前函数执行 print(3) yield 4 print(5) return 6 #函数遇到return语句立即返回,后面的语句不执行 yield 7
next(foo()) #每次运行都是生成新的对象
f = foo()
next(f)
在生成器函数中,可以使用多个yield,每执行一次yield后会暂停执行,把yield表达式的值返回
再次执行会到下一个yield语句又会暂停执行
return语句依然可以终止函数执行,但是return语句的返回值不能被获取到
return语句会导致当前函数返回无法继续进行,也无法获取到下一个值,抛出StopIteration
如果函数没有显式return语句,如果生成器函数执行到结尾,相当于return None,使用next()驱动一样会抛出StopIteration异常
生成器应用
无限循环
def counter(): i = 0 while True: i += 1 yield i c = counter() x = 0 for i in c: x += 1 if x > 10: break print(i)
计数器
def inc(): def counter(): i = 0 while True: i += 1 yield i c = counter() return c
g = inc()
next(g)
def inc(): def counter(): i = 0 while True: i += 1 yield i c = counter() def inner(): return next(c) #用到了闭包 return inner
foo = inc()
foo() #重复执行
#输出
1
2
3
.....
使用lambda匿名函数实现:
def inc(): def counter(): i = 0 while True: i += 1 yield i c = counter() return lambda :next(c) foo = inc() foo() #重复执行 #输出 1 2 3 .....
使用生成器函数计算菲波那切数列:
def fib(): x = 0 y = 1 while True: yield y x, y = y, x + y foo = fib() for x in range(5): print(next(foo))
def inc(): def fib(): x = 0 y = 1 while True: yield y x,y = y,x+y foo = fib() return lambda : next(foo) g = inc() for x in range(10): print(g())
重置功能的计数器:
send()方法:调用send方法,可以吧send的实参传给yield语句做结果,这个结果可以在等式右边被赋值给其他变量
send和next可以推动生成器函数启动并执行

x = yield i 赋值语句,到右边就暂停,x拿到的是None,send驱动同时带一个值过来
def inc(): def counter(): i = 0 while True: i += 1 response = yield i if response is not None: i = response c = counter() def inner(flag=False): if flag: return c.send(0) else: return next(c) return inner #lambda flag=False : c.send(0) if flag else next(c) #第二种写法
g = inc()
g()
g(flag=True)
yield from语法:
yield from就是一种语法糖
def foo(): for i in range(10): yield i #####两个等价####### def foo(): yield from range(10)

浙公网安备 33010602011771号