概述
1,生成器初探
什么是生成器?
可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象.
生成器分类及在Python中的表现形式:(Python中有两种不同的方式提供生成器)
①生成器函数:常规函数定义,但是使用yield语句而不是return语句返回结果.yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行.
②生成器表达式:类似于列表推导,但是生成器返回一个对象,而不是一次构建一个结果列表.
生成器的优点:
Python使用生成器对延迟操作提供了支持.所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果.这也是生成器的主要好处.
生成器小结:
①是可迭代对象
②实现了延迟计算,省内存.
③生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算内存的好处.
2,生成器与yield
若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象.
def my_range(start,stop,step=1):
print('start......')
while start < stop:
yield start
start += step
print('end......')
g = my_range(0,3)
print(g) #
注:生成器内置有__iter__和__next__方法,所以生成器不仅是可迭代对象,同时也是一个迭代器.
因而可以用next(生成器)触发所对应函数的运行
g = my_range(0,3)
#触发函数执行到yield则停止,将yield后的值返回,并在当前位置挂起函数
print(next(g)) #结果:start.... 0
#再次调用next(g),函数从上次暂停的位置继续执行,知道重新遇到yield
print(next(g)) #结果:1
#周而复始
print(next(g)) #结果:2
print(next(g)) #结果:end..... StopIteration
既然生成器对象属于迭代器,那么必然可以使用for循环迭代,如下:
for i in my_range(0,3,1):print(i)
总结:有了yield关键字,我们就有了一种自定义迭代器的实现方式.yield可以用于返回值,但不同于return,函数遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用于返回多次值.
3 深入生成器
yield语句是生成器中的关键语句,生成器在实例化时并不会立即执行,而是等待调用其__next__()方法才开始运行.并且当程序运行完yield语句后就会“吼住“,即保持其当前状态且停止运行,等待下一次遍历时才恢复运行.
yield语句不仅可以使函数成为生成器和返回值,还可以接受调用者传来的数值.但值得注意的是:第一次调用生成器时不能传送给生成器None以外的值,否则会引发错误(TypeError: can't send non-None value to a just-started generator).
defeater():print('ready to eat')whileTrue:
food= yield
print('get the food:%s, and start to eat'%food)
g=eater() #得到生成器对象#需要事先'初始化'一次,让函数挂在food=yield,等待调用g.send()方法为其传值
next(g) #g.send(None)等同于next(g)
g.send('包子')----------------结果-----------------------ready to eat
get the food:包子,and start to eat
#!/usr/bin/env python#-*coding:utf-8-*-
defmy_yield(n):while n>0:
rcv= yieldn
n-= 1
if rcv is notNone:
n=rcv
m= my_yield(3)print(m.send(None))print(next(m))print('传递给生成器一个值,重新初始化生成器.')print(m.send(10))print(next(m))
--------------结果----------------------
3
2
传递给生成器一个值,重新初始化生成器.
10
9
#表达式形式的yield也可以用于返回多次值,即变量名=yield值的形式
defeater():print('Ready to eat')
food_list=[]whileTrue:
food= yieldfood_list
food_list.append(food)
e=eater()
next(e)print(e.send('蒸羔羊'))print(e.send('蒸熊掌'))print(e.send('蒸鹿尾'))
----------------------结果-------------------
Ready to eat
['蒸羔羊']
['蒸羔羊', '蒸熊掌']
['蒸羔羊', '蒸熊掌', '蒸鹿尾']
4 生成器与协程
上述所述的运用send()方法来重置生成器的生成序列,其实也称为协程.协程是一种解决程序并发的方法
1 def consumer(): #定义一个消费者模型
2 print('等待接收处理任务......')3 whileTrue:4 data = (yield)5 print('收到任务:%s'%data)6
7 defproducer():8 c = consumer() #创建一个消费者
9 #c.send(None)
10 c.__next__()11 for i in range(1,5):12 print('发送一个任务...','任务%d'%i)13 c.send('任务%d'%i)14
15 if __name__ == '__main__':16 producer()17
18 ---------------结果------------------
19 等待接收处理任务......20 发送一个任务... 任务121 收到任务:任务122 发送一个任务... 任务223 收到任务:任务224 发送一个任务... 任务325 收到任务:任务326 发送一个任务... 任务427 收到任务:任务4
最后
以上就是单纯唇彩为你收集整理的python调用生成器_Python之生成器的全部内容,希望文章能够帮你解决python调用生成器_Python之生成器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复