如何理解yield的用法

原创不易,转载前请注明博主的链接地址:Blessy_Zhu https://blog.csdn.net/weixin_42555080
本次代码的环境:
运行平台: Windows
Python版本: Python3.x
IDE: PyCharm

1 概述

yield简单来说就是一个生成器,这样函数它记住上次返回时在函数中的位置。对于生成器第二次(或n次)调用跳转至该函数。
在学习Python爬虫的过程中,遇到了一个关键字-yield,刚开始并不能完全理解,查阅了许多博客,把这个内容说的很是复杂费解。后来仔细又理解了一下Java的Iterator迭代器Python生成器还有C语言的概念之后才有更深层、更清晰的理解。


在这里插入图片描述

2 详解

2.1 yield-next()函数

如果你对Python的yield关键字还没有太清晰的认识,如果你有一定的JAVA和C语言的基础,你可以先把yield关键字看作“return”,这是一个类比,为了使更好的理解yield关键字。那话又说回来,return是什么意思就是在程序中返回某个值,返回之后程序就不再往下运行了。看做return之后再把带yield的函数看做一个是生成器(generator)的一部分,如果你还不明白的话,可以通过下面的函数例子,更深刻的理解yield的用法,并且我会对程序的执行顺序和执行内容进行详细的讲解:

def yGenerator():
   print("程序执行到这啦......")
   while True:
       num = yield 1
       print("num的值是:",num)
yg = yGenerator()
print(next(yg))
print('The program is running here,lalalala.......')
print(next(yg))

执行结果是如图1所示


在这里插入图片描述
图1

在这里,定义了一个yGenerator()(yield Generator,就是一个函数名,可以随意命名)函数,函数体里面有一个循环结构,并且在函数外面通过函数赋值调用函数。接下来,分步骤去详细讲解改函数的执行过程:

  • 程序运行后,def yGenerator()函数因为还没有被调用,所以加载(学习过操作系统的人应该可以把此时的代码程序类比于“ready”状态),同时程序继续执行,此时执行到yg = yGenerator(),但是呢!因为函数中有中有yield关键字,所以yGenerator函数并不会真的执行,而是先得到一个生成器yg
  • 接下来程序继续执行到print(next(yg)),此时调用next方法,yGenerator函数正式开始执行,先执行函数中的print方法: print(“程序执行到这啦…”),这就是结果的第一条输出。
  • 然后在函数中继续执行到while循环。程序遇到yield关键字,然后把yield类比return,return了一个1之后,程序停止(continue),接下来什么操作都不进行了,因此并没有执行赋值给num的 操作,此时next(yg)语句执行完成
  • 这样,结果中的前两个行输出:"程序执行到这啦…和1"就分别是:第一个是while上面的print的结果,第二个是return出的结果
  • 接下来执行:print(‘The program is running here,lalalala…’),输出对应内容。
  • 接下来执行第二个print(next(yg)),这个时候和上面那个差不多,不同的是,根据“在哪摔倒在哪爬起来”,这个时候是从刚才那个next程序停止的地方开始执行的,也就是要执行num的赋值操作,但是此时赋值操作的右边是没有值的(因为刚才那个是return出去了,并没有给赋值操作的左边传参数),所以这个时候num赋值是None,所以输出结果就是num的值是:None(一定要注意此时不会再执行print(“程序执行到这啦…”)这个语句,因为在哪退出在哪重新执行的原则)
  • 接下来,因为程序执行完一个while循环后,依然满足条件(实际上这不加限制是一个死循环),所以程序会继续在while里执行,又一次碰到yield,这个时候同样return 出1,然后程序停止,print函数输出的1就是这次return出的1.

2.2 yield-send()函数

接下来,进行一些变化:

def yGenerator():
   print("程序执行到这啦......")
   while True:
       num = yield 1
       print("num的值是:",num)
yg = yGenerator()
print(next(yg))
print('The program is running here,lalalala.......')
print(yg.send(5))

输出结果如图2所示:


在这里插入图片描述
图2

发现此时的num有值了,它的变化就是将最后一句话的next()函数改为yg.send函数,首先呢,先了解一下send()函数的用法:send是发送一个参数给num的,因为上面讲到,return的时候,并没有把1赋值给num,下次执行的时候只好继续执行赋值操作,只好赋值为None了,而如果用send的话,开始执行的时候,先接着上一次(return 1之后)执行,先把5赋值给了num,然后执行next的作用,遇见下一回的yield,return出结果后结束。 也就是说,实际上send()函数,它先执行了自己的send值得操作,然后再执行next()函数的操作。,这样,输出结果为什么是5,就可以知道原因了:由于send方法中包含next()方法,所以程序会继续向下运行执行print方法,然后再次进入while循环
程序执行再次遇到yield关键字,yield会返回后面的值后,程序再次暂停,直到再次调用next方法或send方法。

总结

那么有人就会问了:为什么用这个yield生成器呢?是因为如果用常见的List的话,会占用更大的空间,比如说取0,1,2,3,4,5,6…100
你可能会这样:

for n in range(100):
   a=n

这个时候range(100)就默认生成一个含有100个数的list了,所以很占内存。而yield生成器是可以迭代的,但只可以读取它一次。因为用的时候才生成。比如 mygenerator = (x*x for x in range(3)),注意这里用到了(),它就不是数组,而上面的例子是[],这样就大大节省了内存空间。这篇文章就到这里了,欢迎大佬们多批评指正,也欢迎大家积极评论多多交流。
 

  在这里插入图片描述

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值