首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

搬砖的也能玩Python-进阶篇2

搬砖的也能玩Python——进阶篇

2-生成器

回顾

在第一篇进阶篇中,我们了解了迭代器的相关内容,清楚迭代器的两个主要的方法__next__和__iter__,区分迭代器对象和可迭代对象,本篇文章我们将了解一个特殊的迭代器——生成器(generator)。

一、生成器的相关概念

生成器函数

我们在基础篇6中已经了解了函数的概念,而生成器函数只是在函数的基础上,将return关键字改成yield关键字即可,也就是:

def 函数名(参数):

函数体

yield 返回值

yield每次返回一个结果,通过在每个结果之间挂起和继续它们的状态,来自动实现迭代协议,不需要再明确定义__iter__和__next__方法,就可以达到迭代的效果。

生成器

生成器函数返回生成器的迭代器,而这个“生成器的迭代器”就是我们所说的“生成器”,所以说,生成器是一种特殊的迭代器,可以用for循环进行遍历,可以通过next()方法来获取下一个值。

接下来,我们来看一个生成器的简单例子:

在上图的例子中,我们定义了一个生成器函数,调用函数之后,我们使用__next__()方法,来获得每一个值,在上图的基础上,如果我们再加上一句print(g.__next__()),那么就会出现StopIteration的异常。

由于生成器本身也是迭代器,所以我们也可以用for循环来得到里面的值:

二、生成器的执行顺序

在生成器函数中,我们用了yield每次返回一个结果,具体的执行顺序为:通过__next__()方法开始执行,执行到yield就暂停,返回yield后面的内容,再次使用__next__()方法,则接着上一次暂停的语句处继续执行,执行到yield处停止,如果没有再次找到yield的话,就抛出StopIteration异常。

我们通过下面的例子,来清晰的了解生成器的执行顺序:

在上图的例子中,我们在yield语句的前后都加了print方法,来看一下每次执行__next__()方法时,到底执行了哪些内容。首先来看第一次执行后的结果:

第一次执行之后,我们发现确实只执行到了yield这一句就暂停了,我们继续执行第二次__next__()方法,来看看结果:

为了方便区分这两次__next__()方法,我在中间加了一个分割线,这样一看就很明显了,第二次执行__next__()方法时,先接着上一次暂停的yield语句继续执行,先执行了print("yield之后的语句")方法,然后一直执行到yield语句,然后暂停。

我们执行完所有的__next__()方法:

当执行到最后一个__next__()方法时,此时已经结束了while循环,也就无法再找到yield方法,便会抛出StopIteration异常。我们来看一下最终的结果:

三、生成器表达式

生成器表达式可以帮助我们每次获取一个元素,并对该元素进行解析,这样通过生成器一边循环一边计算,可以节省大量的空间。具体的表达式格式如下:

(exprforiter_variniterableifcond_expr)

一个生成器表达式,用圆括号括起来,先迭代iterable中的内容,每一次迭代会判断迭代的内容是否满足cond_expr条件表达式,如果满足,就把内容赋值给iter_var,然后再执行expr这个表达式,expr得到的结果就相当于yield后面的语句。来看下面这个例子:

这就是一个生成器表达式,由于生成器表达式得到的是一个生成器,所以我们可以直接使用__next__()方法或者for循环来进行遍历。

四、yield交互(send、close方法)

在生成器中,我们还有一个有意思的地方,就是yield可以作为一个表达式来赋值,也就是val = yield。那么问题就来了,yield的值从哪里来呢?

这就需要send()方法了,send()方法传入的参数,就是yield的值。

注意

通过前面的学习,我们知道在使用__next__()方法时,执行到yield就暂停,再次执行__next__()时,才能继续执行后面的内容。我们send()方法的大前提就是:生成器必须处于在yield位置暂停的状态,才可以用send()方法给yield传递值。

所以,在使用send()方法给yield传递值之前,必须使用__next__()方法,先让生成器暂停才行,否则会有异常抛出。

我们来看一下send()方法的例子:

如果我们不执行g.__next__()方法,直接执行g.send("abc"),会有如下报错:

通过使用close()方法,可以关闭当前的生成器,当生成器关闭之后,再使用__next__()方法和send()方法,便会抛出StopIteration异常。

探测八个蛋∣跳出手工测试的井

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180224G19B4U00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券