python生成器yield原理_生成器yield关键字详解

鉴于yield关键字的原理大家理解的都不是很深刻,今天我们主要就这一课题进行探讨。

生成器可以用什么方式得到?

方法一:

利用推导式的方式得到生成器# 列表推导式

list1 = [i for i in range(9)]

print(list1)

# 得到生成器

generator = (i for i in range(9))

print(generator)

执行结果:

[0, 1, 2, 3, 4, 5, 6, 7, 8]

 at 0x00000151D63DA830>

方式二:

利用函数的方式,用yield得到生成器def generator():

print('代码开始执行了。。。。。。。。')

while True:

response = yield 1

print('-------------------------------')

print('response = ', response)

g = generator()

print(g)

执行结果:

那么我们现在正式来说说这个yield关键字,来解开它的神秘面纱。

从这个程序中大家看到了什么,是不是我们的这个执行结果并不是一个function,而是一个generator,这个就是我们的这个yield关键字的效果,只要我们在函数中使用了yield关键字,那么它不在是一个函数,而是一个生成器。而且,大家还可以看到,我们的这个print语句并没有执行,大家是否有很多问号?

那么这个原因还是和它变成了一个生成器的原因所导致的。生成器一样的会和input函数一样起一个类似的阻塞作用,需要你调用它内部的next方法才会使程序执行一次,当你再一次遇到yield的时候,同样又会停止,那我们来试一下。def generator():

print('代码开始执行了。。。。。。。。')

while True:

response = yield 1

print('-------------------------------')

print('response = ', response)

g = generator()

print(g)

print(next(g))

执行结果:

代码开始执行了。。。。。。。。

1

现在大家看到了什么现象,是不是我们调用了这个next方法之后,代码开始正常执行了,并且给我们返回出了一个1,由此可以证明yield同样还有一个类似于return的功能。但是我们从这个执行结果来看,是不是发现了yield关键字下面的代码没有执行啊?这也就是我说的,遇到了yield就会停止的情况。如果我们现在再去调用一次next方法。def generator():

print('代码开始执行了。。。。。。。。')

while True:

response = yield 1

print('-------------------------------')

print('response = ', response)

g = generator()

print(g)

print(next(g))

print(next(g))

执行结果:

代码开始执行了。。。。。。。。

1

-------------------------------

response =  None

1

那么现在大家发现了没有,我们打印出了三个数据之后又停止了。但是和上面的执行结果对比我们就不难发现,我们第二次调用next方法的时候,并不是自上往下执行的,而是从上一次停止的位置继续执行的,这也就是我们的生成器的特性,它会记住你上一次停留的地方,下次继续从这个地方开始执行。

那好,这是一个现象,大家在看到response = None这块,为什么会出现这么个结果,是不是有同学会纳闷,它的结果不应该是1吗?怎么会是None呢?这里我要告诉大家的是,这个1的结果已经被我们的yield返回出去了,所以这里没有数据,这也是生成器的另一个特征之一,你取出去了这个数据,那么这个数据在生成器里面就不存在了,当你把生成器里的数据取完了,那么它就不能够继续使用了,也就是说生成器只能用一次。

我们再来看第三个现象,最后有一个1是从哪里输出的?它是下一次循环的yield返回出来的,同样到了这里,yield再次将程序阻塞到了这里,知道再次调用next方法或者send方法。

那么看到这里,是不是又有同学们会纳闷了,老师你说的这个next方法我知道,但是这个send方法又是什么东西啊,为什么说send也可以调用这个生成器呢?不急,我们先来写一下这个代码。def generator():

print('代码开始执行了。。。。。。。。')

while True:

response = yield 1

print('-------------------------------')

print('response = ', response)

g = generator()

print(g)

print(next(g))

print(next(g))

print(g.send(2))

执行结果:

代码开始执行了。。。。。。。。

1

-------------------------------

response =  None

1

-------------------------------

response =  2

1

其实对于我们这个send方法,大家应该不难看到,他就是给我们的response传了一个值而已,那么它为什么同样能够调用出我们的生成器呢?那是因为send同样也是在Generator内部的一个方法,它的里面同样封装了next方法,所以我们调用send方法同样也是可以调用到生成器的。并且可以给yield的赋值对象传递一个值。

现在大家对于我们这个yield关键字应该有了深刻的理解了吧?面试官问你,就这么干掉他,你get到了吗?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值