简单了解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算法学习之基数排序实例
Dec 18 Python
Ruby使用eventmachine为HTTP服务器添加文件下载功能
Apr 20 Python
python音频处理用到的操作的示例代码
Oct 27 Python
django项目运行因中文而乱码报错的几种情况解决
Nov 07 Python
Python使用requests及BeautifulSoup构建爬虫实例代码
Jan 24 Python
Python模块文件结构代码详解
Feb 03 Python
Python爬虫框架Scrapy常用命令总结
Jul 26 Python
选择Python写网络爬虫的优势和理由
Jul 07 Python
Python调用scp向服务器上传文件示例
Dec 22 Python
python分别打包出32位和64位应用程序
Feb 18 Python
解决Jupyter notebook中.py与.ipynb文件的import问题
Apr 21 Python
Python查找算法的实现 (线性、二分,分块、插值查找算法)
Apr 24 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
超小PHP小马小结(方便查找后门的朋友)
2012/05/05 PHP
php中引用符号(&amp;)的使用详解
2013/11/13 PHP
php 中phar包的使用教程详解
2018/10/26 PHP
jquery 操作单选框,复选框,下拉列表实现代码
2009/10/27 Javascript
jQuery+ajax实现顶一下,踩一下效果
2010/07/17 Javascript
jQuery实现网站添加高亮突出显示效果的方法
2015/06/26 Javascript
jquery实现点击展开列表同时隐藏其他列表
2015/08/10 Javascript
js显示当前日期时间和星期几
2015/10/22 Javascript
利用jQuery及AJAX技术定时更新GridView的某一列数据
2015/12/04 Javascript
AngularJS入门教程之更多模板详解
2016/08/19 Javascript
基于vue2框架的机器人自动回复mini-project实例代码
2017/06/13 Javascript
Vue 兄弟组件通信的方法(不使用Vuex)
2017/10/26 Javascript
Vue实现侧边菜单栏手风琴效果实例代码
2018/05/31 Javascript
微信小程序实现按字母排列选择城市功能
2019/11/25 Javascript
vue+springboot图片上传和显示的示例代码
2020/02/14 Javascript
[52:20]VP vs VG Supermajor小组赛 B组胜者组决赛 BO3 第一场 6.2
2018/06/03 DOTA
[01:09:13]DOTA2-DPC中国联赛 正赛 CDEC vs XG BO3 第三场 1月19日
2021/03/11 DOTA
Python Sleep休眠函数使用简单实例
2015/02/02 Python
在Python中使用__slots__方法的详细教程
2015/04/28 Python
python数据类型_元组、字典常用操作方法(介绍)
2017/05/30 Python
基于Python 装饰器装饰类中的方法实例
2018/04/21 Python
pyttsx3实现中文文字转语音的方法
2018/12/24 Python
python爬虫 爬取58同城上所有城市的租房信息详解
2019/07/30 Python
Shoes For Crews法国官网:美国领先的防滑鞋设计和制造商
2018/01/01 全球购物
美体小铺印度官网:The Body Shop印度
2019/10/17 全球购物
英国Lookfantastic中文网站:护肤品美妆美发购物(英国直邮)
2020/04/27 全球购物
是什么让J2EE适合用来开发多层的分布式的应用
2015/01/16 面试题
介绍一下XMLHttpRequest对象
2012/02/12 面试题
计算机毕业大学生推荐信
2013/12/01 职场文书
2014世界杯球队球队口号
2014/06/05 职场文书
领导干部个人对照检查材料(群众路线)
2014/09/26 职场文书
升学宴答谢词
2015/01/05 职场文书
2016基督教会圣诞节开幕词
2016/03/04 职场文书
新员工入职感言范文!
2019/07/04 职场文书
浅谈如何提高PHP代码质量之端到端集成测试
2021/05/28 PHP
浅谈Go语言多态的实现与interface使用
2021/06/16 Golang