python调用生成器_Python之生成器

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值