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

干货!python入门基础之生成器与yield详解

本文从以下三个方面介绍:

生成器概念

生成器用法

使用生成器的好处(作用)

一、生成器概念:

Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。主要有两种结构可以延迟结果创建。生成器函数和生成器表达式。

生成器函数:和其他函数编写方式相同,但是使用yield语句一次返回一个结果,在每个结果之间挂起当前状态,下次调用的时候会从当前状态继续。例如:

我们发现它在for循环中输出的值是接上一条语句调用之后的。

生成器表达式:类似于列表解析,不同的是它返回的是一个可迭代对象而不是一个列表。

例如:

注意:生成器是一个对象,我们用的是()而不是【】。用【】就等于创建一个列表。

一句话总结,任何使用了yield的函数就是生成器,生成器就是一个返回迭代器的函数,或者说生成器就是一个迭代器。

二、总结yield

1.和return相似,返回值。

2.暂停迭代,直到调用下一个next()方法。

3.调用的时候返回生成器对象。

三、生成器的用法:

1、close()方法

close()方法就是关闭生成器。生成器被关闭后,再次调用next()方法,不管能否遇到yield关键字,都会立即抛出StopIteration异常。

2、send()方法

这是我认为生成器最重要的功能,我们可以通过send()方法,向生成器内部传递参数。我们来看个例子:

我们第一次传进去的值将value赋值为5,第一次调用x输出值为0,然后我们将参数传进去,改变了value的值,再次输出就是我们传入的值了。简单的说,send()就是next()的功能,加上传值给yield。

3、throw()方法

除了向生成器函数内部传递参数,我们还可以传递异常。还是先看例子:

我们传入了valueError的异常,成功触发了except中的异常。

4、用yield实现斐波那契数列:

四、生成器的好处(作用)?

我们发现生成器和迭代器差不多,但是用生成器有什么好处?

1、节省内存,特别是大量数据的时候。比如我们生成一个列表:mylist = [1, 2, 3],也可以是mylist = [x**2 for x in range(3)],但是这样程序运行的时候,列表的数据全部存储在内存中,当数据量特别大的时候,会特别消耗内存。但是,利用生成器我们可以这样gen = (x ** 2 for x in range(4)),生成器只有在用的时候会生成,所以,当我们没有用到这个列表的时候它就不会存在,也不会占内存。

如果有人不信可以试试这这两段代码:

分开运行哦,记得看看内存和cpu占用(里面0尽量多一点)

2、 节省代码,减少代码量同时提高代码可读性。请看下面两个函数,他们实现的功能是相同的,但是利用生成器代码量就会减少。

3、 模拟并发。Python虽然支持多线程,但是由于GIL(全局解释锁,Global Interpreter Lock)的存在,同一个时间,只能有一个线程在运行,所以无法实现真正的并发。这时就出现了协程。复杂解释不说了,简单说协程就是你可以暂停执行的函数"。也就是yield。

Python实现协程最简单的方法,就是使用yield。当一个函数在执行过程中被阻塞时,就用yield挂起,然后执行另一个函数。当阻塞结束后,可以用next()或者send()唤醒。相比多线程,协程的好处是它在一个线程内执行,避免线程之间切换带来的额外开销,而且协程不存在加锁的步骤。

下面是一个生产者与消费者例子:

执行结果

通过执行结果,我们会看到控制台交替打印出生产和消费的结果。消费者consumer()函数是一个生成器函数,每次执行到yield时即挂起,并返回上一次的结果给生产者。生产者producer()接收到生成器的返回,并生成一个新的值,通过send()方法发送给消费者。至此,我们成功实现了一个(伪)并发。

码字不易,多多关注,谢谢。不足之处欢迎指正。

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

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券