一文搞懂Python迭代器和生成器
很多童鞋搞不懂python迭代器和生成器到底是什么?它们之间又有什么样的关系?
这篇文章就是要用最简单的方式让你理解Python迭代器和生成器!

1、迭代器和迭代过程
维基百科解释道:
在Python中,迭代器是遵循迭代协议的对象。使用iter()从任何序列对象中得到迭代器(如list, tuple, dictionary, set等)。另一种形式的输入迭代器是generator(生成器)。
很多容器诸如列表、字符串可以用for循环遍历对象。for 语句会调用容器对象中的 iter()函数, 该函数返回一个定义了 __next__() 方法的迭代器对象,该方法将逐一访问容器中的元素。
所以说:python中,任意对象,只要定义了__next__方法,它就是一个迭代器。因此,python中的容器如列表、元组、字典、集合、字符串都可以被称作迭代器。

讲完迭代器后,迭代就比较好理解了,迭代就是从迭代器中取元素的过程。
比如我们用for循环从列表[1,2,3]中取元素,这种遍历过程就被称作迭代。
# 列表是迭代器
for element in [1, 2, 3]:
print(element)
# 元组是迭代器
for element in (1, 2, 3):
print(element)
# 字典是迭代器
for key in {'one':1, 'two':2}:
print(key)
# 字符串是迭代器
for char in "123":
print(char)
# 打开的text同样是迭代器
for line in open("myfile.txt"):
print(line, end='')
如果你不想用for循环迭代呢?这时你可以:
- 先调用容器(以字符串为例)的iter()函数
- 再使用 next() 内置函数来调用 __next__() 方法
- 当元素用尽时,__next__() 将引发 StopIteration 异常

>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
next(it)
StopIteration
2、生成器 Generators
看看廖雪峰大神的解释:
通过列表生成式,我们可以直接创建一个列表。
但是,受到内存限制,列表容量肯定是有限的。
而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?
这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。
生成器也是一种迭代器,但是你只能对其迭代一次。这是因为它们并没有把所有的值存在内存中,而是在运行时生成值。
你通过遍历来使用它们,要么用一个for循环,要么将它们传递给任意可以进行迭代的函数和结构。大多数时候生成器是以函数来实现的。然而,它们并不返回一个值,而是yield(暂且译作“生出”)一个值。
每次对生成器调用 next() 时,它会从上次离开位置恢复执行(它会记住上次执行语句时的所有数据值)。显示如何非常容易地创建生成器的示例如下:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse('golf'):
... print(char)
...
f
l
o
g
可以用生成器来完成的操作同样可以用前一节所描述的基于类的迭代器来完成。但生成器的写法更为紧凑,因为它会自动建 __iter__() 和 __next__()方法。
3、生成器表达式
生成器不一定要用复杂的函数表示,python提供了简洁的生成器表达式。
从形式上来看,生成器表达式和列表推导式很像,仅仅是将列表推导式中的[]替换为(),但是两者差别挺大,生成器表达式可以说组合了迭代功能和列表解析功能。
生成器表达式可以认为是一种特殊的生成器函数,类似于lambda表达式和普通函数。但是和生成器一样,生成器表达式也是返回生成器generator对象,一次只返回一个值。
>>> sum(i*i for i in range(10)) # sum of squares
285
>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum(x*y for x,y in zip(xvec, yvec)) # dot product
260
>>> from math import pi, sin
>>> sine_table = {x: sin(x*pi/180) for x in range(0, 91)}
>>> unique_words = set(word for line in page for word in line.split())
>>> valedictorian = max((student.gpa, student.name) for student in graduates)
>>> data = 'golf'
>>> list(data[i] for i in range(len(data)-1, -1, -1))
['f', 'l', 'o', 'g']
如果大家想要学习更多的python数据分析知识,请关注我的公众号:pydatas

一文搞懂Python迭代器和生成器的更多相关文章
- 一文搞懂Python可迭代、迭代器和生成器的概念
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...
- 一文搞懂Python Unittest测试方法执行顺序
大家好~我是米洛! 欢迎关注我的公众号测试开发坑货,一起交流!点赞收藏关注,不迷路. Unittest unittest大家应该都不陌生.它作为一款博主在5-6年前最常用的单元测试框架,现在正被pyt ...
- 一文搞懂 Python 的模块和包,在实战中的最佳实践
最近公司有个项目,我需要写个小爬虫,将爬取到的数据进行统计分析.首先确定用 Python 写,其次不想用 Scrapy,因为要爬取的数据量和频率都不高,没必要上爬虫框架.于是,就自己搭了一个项目,通过 ...
- 一文搞懂Python函数(匿名函数、嵌套函数、闭包、装饰器)!
Python函数定义.匿名函数.嵌套函数.闭包.装饰器 目录 Python函数定义.匿名函数.嵌套函数.闭包.装饰器 函数核心理解 1. 函数定义 2. 嵌套函数 2.1 作用 2.2 函数变量作用域 ...
- 一文搞懂Python中的所有数组数据类型
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...
- 一文搞懂所有Java集合面试题
Java集合 刚刚经历过秋招,看了大量的面经,顺便将常见的Java集合常考知识点总结了一下,并根据被问到的频率大致做了一个标注.一颗星表示知识点需要了解,被问到的频率不高,面试时起码能说个差不多.两颗 ...
- 一文搞懂RAM、ROM、SDRAM、DRAM、DDR、flash等存储介质
一文搞懂RAM.ROM.SDRAM.DRAM.DDR.flash等存储介质 存储介质基本分类:ROM和RAM RAM:随机访问存储器(Random Access Memory),易失性.是与CPU直接 ...
- 基础篇|一文搞懂RNN(循环神经网络)
基础篇|一文搞懂RNN(循环神经网络) https://mp.weixin.qq.com/s/va1gmavl2ZESgnM7biORQg 神经网络基础 神经网络可以当做是能够拟合任意函数的黑盒子,只 ...
- Python 迭代器和生成器(转)
Python 迭代器和生成器 在Python中,很多对象都是可以通过for语句来直接遍历的,例如list.string.dict等等,这些对象都可以被称为可迭代对象.至于说哪些对象是可以被迭代访问的, ...
随机推荐
- RDS数据库磁盘满导致实例锁定
问题描述: 阿里云RDS空间不足,进行报警.收到报警后.对数据库中不重要的数据备份后执行delete删除操作.执行成功后发现数据删掉了.但是数据库的空间并没有释放.数据占用空间反而越来越大,最后RDS ...
- 学习kafka自己发生的几个小错误记录
一. The method iterator() is ambiguous ConsumerIterator<byte[],byte[]> it =stream.iterator(); ...
- 未能加载文件或程序集“Seagull.BarTender.Print, Version=11.0.8.1, Culture=neutral, PublicKeyToken=109ff779a1b4cbc7
这2天项目上需要使用BarTender打印软件,使用BarTender的库的时候时候发现一个特别的问题: 未能加载文件或程序集“Seagull.BarTender.Print, Version=11. ...
- django实战仿慕课网在线视频网站(完成了85%以上的功能已上传github:https://github.com/huwei86/mxonline):
1. 前台功能模块 基本模块:登录 注册 找回密码 / 全局搜索 / 个人中心, 课程功能:课程管理 / 讲师管理 / 授课机构管理 热门推荐 相关课程推荐 用户操作管理:用户收藏 / 课程评论 ...
- Linux命令学习-ls命令
Linux中,ls命令的全称是list,主要作用是列出当前目录下的清单. 列出Linux根目录下的所有目录 ls / 列出当前目录下所有文件夹和文件 ls 列出当前目录下所有文件夹和文件(包括以&qu ...
- Linux命令学习-mkdir命令
Linux中,mkdir命令的全称是make directory,即创建目录的意思. 假设当前处于wintest用户的主目录,路径为 /home/wintest ,存在文件夹testA,进入testA ...
- .NET项目迁移到.NET Core操作指南
为什么要从.NET迁移到.NET Core? .NET Core提供的特性 .NET Core性能提升 .NET如何迁移到.NET Core? 迁移工作量评估(API兼容性分析) 迁移方案制定 通过类 ...
- activiti学习笔记
activiti入门 activiti官网 pom.xml文件 xml <!-- activiti --> <dependency> <groupId>org.ac ...
- 【朝花夕拾】Android自定义View篇之(十一)View的滑动,弹性滑动与自定义PagerView
前言 由于手机屏幕尺寸有限,但是又经常需要在屏幕中显示大量的内容,这就使得必须有部分内容显示,部分内容隐藏.这就需要用一个Android中很重要的概念——滑动.滑动,顾名思义就是view从一个地方移动 ...
- C# 中异常抛出捕获机制--throw / try,catch,finally
try { messagebox.show("true"); } catch { messagebox.show("false"); } finally { m ...