生成器
生成器指的是生成器对象,可以由生成器表达式生成,也可以使用yield关键字编写一个生成器函数,调用这个函数得到一个生成器对象。
生成器对象是一个可迭代对象,是一个迭代器
生成器对象是延时计算,惰性求值的对象
m = (i for i in range(10))
type(m)m
(generator, at 0x000001AFE65720A0>)
生成器函数
函数体中包含yield关键字的函数,就是生成器函数,调用后返回生成器对象
defg():for i in range(10):yieldi
f=g()
type(f),f
(generator,)
可使用next(f)驱动
普通函数调用,函数会立即执行,直到执行结束,生成器函数调用,并不会立即执行函数体,而是返回一个生成器对象,需要使用next()内嵌函数来驱动这个生成器对象
生成器表达式和生成器函数都可以得到一个生成器对象,只不过生成器函数可以写的更加的复杂。
生成器函数的执行
deffoo():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异常
生成器应用
无限循环
defcounter():
i=0whileTrue:
i+= 1
yieldi
c=counter()
x=0for i inc:
x+= 1
if x > 10:break
print(i)
计数器
definc():defcounter():
i=0whileTrue:
i+= 1
yieldi
c=counter()return c
g = inc()
next(g)
definc():defcounter():
i=0whileTrue:
i+= 1
yieldi
c=counter()definner():returnnext(c) #用到了闭包return inner
foo = inc()
foo() #重复执行
#输出
1
2
3
.....
使用lambda匿名函数实现:
definc():defcounter():
i=0whileTrue:
i+= 1
yieldi
c=counter()return lambda:next(c)
foo=inc()
foo()#重复执行#输出
1
2
3.....
使用生成器函数计算菲波那切数列:
deffib():
x=0
y= 1
whileTrue:yieldy
x, y= y, x +y
foo=fib()for x in range(5):print(next(foo))
definc():deffib():
x=0
y= 1
whileTrue:yieldy
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驱动同时带一个值过来
definc():defcounter():
i=0whileTrue:
i+= 1response= yieldiif response is notNone:
i=response
c=counter()def inner(flag=False):ifflag:returnc.send(0)else:returnnext(c)returninner#lambda flag=False : c.send(0) if flag else next(c) #第二种写法
g = inc()
g()
g(flag=True)
yield from语法:
yield from就是一种语法糖
deffoo():for i in range(10):yieldi#####两个等价#######
deffoo():yield from range(10)