简单了解Python生成器是什么


Posted in Python onJuly 02, 2019

前言

生成器是 Python 初级开发者最难理解的概念之一,虽被认为是 Python 编程中的高级技能,但在各种项目中可以随处见到生成器的身影,你得不得去理解它、使用它、甚至爱上它。

提到生成器,总不可避免地要把迭代器拉出来对比着讲,生成器就是一个在行为上和迭代器非常类似的对象,如果把迭代器比作 Android 系统,那么生成器就是 iOS,二者功能上差不多,但是生成器更优雅。

什么是迭代器
顾名思义,迭代器就是用于迭代操作(for 循环)的对象,它像列表一样可以迭代获取其中的每一个元素,任何实现了 __next__ 方法 (python2 是 next)的对象都可以称为迭代器。

它与列表的区别在于,构建迭代器的时候,不像列表把所有元素一次性加载到内存,而是以一种延迟计算(lazy evaluation)方式返回元素,这正是它的优点。比如列表含有中一千万个整数,需要占超过400M的内存,而迭代器只需要几十个字节的空间。因为它并没有把所有元素装载到内存中,而是等到调用 next 方法时候才返回该元素(按需调用 call by need 的方式,本质上 for 循环就是不断地调用迭代器的next方法)。

以斐波那契数列为例来实现一个迭代器:

class Fib:
def __init__(self, n):
self.prev = 0
self.cur = 1
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.n > 0:
value = self.cur
self.cur = self.cur + self.prev
self.prev = value
self.n -= 1
return value
else:
raise StopIteration()
# 兼容python2
def __next__(self):
return self.next()
f = Fib(10)
print([i for i in f])
#[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

什么是生成器

知道迭代器之后,就可以正式进入生成器的话题了。普通函数用 return 返回一个值,和 Java 等其他语言是一样的,然而在 Python 中还有一种函数,用关键字 yield 来返回值,这种函数叫生成器函数,函数被调用时会返回一个生成器对象,生成器本质上还是一个迭代器,也是用在迭代操作中,因此它有和迭代器一样的特性,唯一的区别在于实现方式上不一样,后者更加简洁

最简单的生成器函数:

>>> def func(n):
... yield n*2
...
>>> func
<function func at 0x00000000029F6EB8>
>>> g = func(5)
>>> g
<generator object func at 0x0000000002908630>
>>>

func 就是一个生成器函数,调用该函数时返回对象就是生成器 g ,这个生成器对象的行为和迭代器是非常相似的,可以用在 for 循环等场景中。注意 yield 对应的值在函数被调用时不会立刻返回,而是调用next方法时(本质上 for 循环也是调用 next 方法)才返回

>>> g = func(5)
>>> next(g)
10
>>> g = func(5)
>>> for i in g:
... print(i)
...
10

那为什么要用生成器呢?显然,用生成器在逼格上要比迭代器高几个等级,它没有那么多冗长代码了,而且性能上一样的高效,为什么不用呢?来看看用生成器实现斐波那契数列有多简单。

def fib(n):
prev, curr = 0, 1
while n > 0:
n -= 1
yield curr
prev, curr = curr, curr + prev
print([i for i in fib(10)])
#[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

生成器表达式

在前面一期「这样写代码更优雅」的文章里面曾经介绍过列表推导式(list comprehension),生成器表达式与列表推导式长的非常像,但是它俩返回的对象不一样,前者返回生成器对象,后者返回列表对象。

>>> g = (x*2 for x in range(10))
>>> type(g)
<type 'generator'>
>>> l = [x*2 for x in range(10)]
>>> type(l)
<type 'list'>

前面已经介绍过生成器的优势,就是迭代海量数据时,显然生成器更合适。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
一步步解析Python斗牛游戏的概率
Feb 12 Python
Python设计模式编程中解释器模式的简单程序示例分享
Mar 02 Python
python、java等哪一门编程语言适合人工智能?
Nov 13 Python
python不换行之end=与逗号的意思及用途
Nov 21 Python
python计算两个地址之间的距离方法
Jun 09 Python
Sanic框架应用部署方法详解
Jul 18 Python
Python+OpenCV图片局部区域像素值处理详解
Jan 23 Python
Python 实现日志同时输出到屏幕和文件
Feb 19 Python
在django admin详情表单显示中添加自定义控件的实现
Mar 11 Python
零基础学Python之前需要学c语言吗
Jul 21 Python
一些关于python 装饰器的个人理解
Aug 31 Python
python logging模块的使用
Sep 07 Python
Python OpenCV 调用摄像头并截图保存功能的实现代码
Jul 02 #Python
使用python实现ftp的文件读写方法
Jul 02 #Python
Python初学者常见错误详解
Jul 02 #Python
Python使用pyserial进行串口通信的实例
Jul 02 #Python
Python函数中参数是传递值还是引用详解
Jul 02 #Python
Python 运行.py文件和交互式运行代码的区别详解
Jul 02 #Python
python 函数中的内置函数及用法详解
Jul 02 #Python
You might like
mysql 查询指定日期时间内sql语句实现原理与代码
2012/12/16 PHP
PHP不使用递归的无限级分类简单实例
2016/11/05 PHP
TP5(thinkPHP5框架)基于bootstrap实现的单图上传插件用法示例
2019/05/29 PHP
THINKPHP5分页数据对象处理过程解析
2020/10/28 PHP
js+FSO遍历文件夹下文件并显示
2007/03/07 Javascript
JavaScript入门教程(8) Location地址对象
2009/01/31 Javascript
JavaScript效率调优经验
2009/06/04 Javascript
解析John Resig Simple JavaScript Inheritance代码
2012/12/03 Javascript
用json方式实现在 js 中建立一个map
2014/05/02 Javascript
jquery点击缩略图切换视频播放特效代码分享
2015/09/15 Javascript
jQuery实现的超简单点赞效果实例分析
2015/12/31 Javascript
利用jquery制作滚动到指定位置触发动画
2016/03/26 Javascript
微信小程序使用第三方库Underscore.js步骤详解
2016/09/27 Javascript
jQuery表格的维护和删除操作
2017/02/03 Javascript
canvas滤镜效果实现代码
2017/02/06 Javascript
vue.js实现数据动态响应 Vue.set的简单应用
2017/06/15 Javascript
angular select 默认值设置方法
2017/06/23 Javascript
详解使用nvm管理多版本node的方法
2017/08/30 Javascript
利用jsonp与代理服务器方案解决跨域问题
2017/09/14 Javascript
jsonp跨域及实现百度首页联想功能的方法
2018/08/30 Javascript
微信小程序使用scroll-view标签实现自动滑动到底部功能的实例代码
2018/11/09 Javascript
[22:59]VGJ.S vs VG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
wxPython窗口中文乱码解决方法
2014/10/11 Python
hmac模块生成加入了密钥的消息摘要详解
2018/01/11 Python
使用 Python 玩转 GitHub 的贡献板(推荐)
2019/04/04 Python
python定时复制远程文件夹中所有文件
2019/04/30 Python
python:按行读入,排序然后输出的方法
2019/07/20 Python
详解如何在pyqt中通过OpenCV实现对窗口的透视变换
2020/09/20 Python
荷兰本土平价百货:HEMA
2017/10/23 全球购物
某IT外企面试题-二分法求方程!看看大家的C++功底
2015/07/04 面试题
C++是不是类型安全的
2014/02/18 面试题
JAVA高级程序员面试题
2013/09/06 面试题
艺术爱好者的自我评价分享
2013/10/08 职场文书
应聘护理专业毕业自荐书范文
2014/02/12 职场文书
2014年城市管理工作总结
2014/12/02 职场文书
2015年上半年党建工作总结
2015/03/30 职场文书