Python之可迭代对象、迭代器、生成器
在使用Python的过程中,很容易混淆如下几个关联的概念:
1.容器(container)
2.可迭代对象(Iterable)
3.迭代器(Iterator)
4.生成器(generator)
5.生成器表达式
6.{list, set, dict} 解析式
它们之间的关系如下表所示:

容器(container)
容器是用来储存元素的一种数据结构,它支持隶属测试,容器将所有数据保存在内存中,在Python中典型的容器有:
list, deque, …
set,frozesets,…
dict, defaultdict, OrderedDict, Counter, …
tuple, namedtuple, …
str
容器相对来说很好理解,因为你可以把它当成生活中的箱子、房子、船等等。
一般的,通过判断一个对象是否包含某个元素来确定它是否为一个容器。例如:
字典容器通过检查是否包含键来进行判断:
字符串通过检查是否包含某个子 串来判断:
注意:并非所有的容器都是可迭代对象。
可迭代对象
正如前面所提到的,大部分容器都是可迭代的,但是还有其他一些对象也可以迭代,例如,文件对象以及管道对象等等,容器一般来说存储的元素是有限的,同样的,可迭代对象也可以用来表示一个包含有限元素的数据结构。
可迭代对象可以为任意对象,不一定非得是基本数据结构,只要这个对象可以返回一个iterator。听起来可能有点费解,但是可迭代对象与迭代器之间有一个显著的区别。先看下面的例子
注意:可迭代的类中,一般实现以下两个方法,__iter__()以及__next()__方法,__iter__()方法返回self。
当我们运行以下代码的时候:
|
1 2 3 |
x = [1,2,3] for elem in x: ... |
实际调用过程如下:
当我们反向编译这段代Python码的时候,可以发现它显示调用了 GET_ITER,本质上跟调用iter(x)一样,而FOR_ITER指令相等于调用next()方法来获取每个元素。
>>> import dis
>>> x = [1,2,3]
>>> dis.dis('for _ in x: pass')
1 0 SETUP_LOOP 12 (to 14)
2 LOAD_NAME 0 (x)
4 GET_ITER
>>
6 FOR_ITER 4 (to
12)
8 STORE_NAME 1 (_)
10 JUMP_ABSOLUTE 6
>> 12 POP_BLOCK
>> 14 LOAD_CONST 0 (None)
16 RETURN_VALUE
迭代器(Iterators)
那么什么是迭代器呢?任何具有__next__()方法的对象都是迭代器,对迭代器调用next()方法可以获取下一个值。而至于它使如何产生这个值的,跟它能否成为一个迭代器并没有关系。所以迭代器本质上是一个产生值的工厂,每次向迭代器请求下一个值,迭代器都会进行计算出相应的值并返回。
迭代器的例子很多,例如,所有itertools模块中的函数都会返回一个迭代器,有的还可以产生无穷的序列。
有的函数根据有限序列中生成无限序列:
|
2 3 4 5 6 7 8 9 10 |
>>> from itertools import cycle >>> colors = >>> next(colors) "red" >>> next(colors) "white" >>> next(colors) "blue" >>> next(colors) "red" |
有的函数根据无限序列中生成有限序列:
>>> from itertools import islice
>>> colors = cycle(['red', 'white',
'blue']) # infinite
>>> limited=islice(colors,0,
4) # finite
>>> for x in
limited: #
so safe to use for-loop on
... print(x)
red
white
blue
Red
为了更好的理解迭代器的内部结构,我们先来定义一个生成斐波拉契数的迭代器:
>>> class fib:
...
def __init__(self):
...
self.prev = 0
...
self.curr = 1
...
...
def __iter__(self):
...
return self
...
...
def __next__(self):
...
value = self.curr
...
self.curr += self.prev
...
self.prev = value
...
return value
...
>>> f = fib()
>>> list(islice(f, 0, 10))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
注意这个类既是可迭代的 (因为具有__iter__()方法),也是它自身的迭代器(因为具有__next__()方法)。
迭代器内部状态保存在当前实例对象的prev以及cur属性中,在下一次调用中将使用这两个属性。每次调用next()方法都会执行以下两步操作:
修改状态,以便下次调用next()方法
计算当前调用的结果
比喻:从外部来看,迭代器就像政府工作人员一样,没人找他办事的时候(请求值),工作人员就闲着,当有人来找他的时候(请求值),工作人员就会忙一会,把请求的东西找出来交给请求的人。忙完之后,又没事了,继续闲着。
生成器
生成器其实就是一种特殊的迭代器。它shi一种更为高级、更为优雅的迭代器。
使用生成器让我们可以以一种更加简洁的语法来定义迭代器。
让我们先明确以下两点:
任意生成器都是迭代器(反过来不成立)
任意生成器,都是一个可以延迟创建值的工厂
下面也是一个生成斐波那契序列的工厂函数,不过是以生成器的方式编写的:
生成器的类型
在Python中两种类型的生成器:生成器函数以及生成器表达式。生成器函数就是包含yield参数的函数。生成器表达式与列表解析式类似。
Python之可迭代对象、迭代器、生成器的更多相关文章
- 深入理解python中可迭代对象,迭代器,生成器
英文原文出处:Iterables vs. Iterators vs. Generators 在python学习中,通常会陷入对以下几个相关概念之间的确切差异的困惑中: a container(容器) ...
- 可迭代对象&迭代器&生成器
在python中,可迭代对象&迭代器&生成器的关系如下图: 即:生成器是一种特殊的迭代器,迭代器是一种特殊的可迭代对象. 可迭代对象 如上图,这里x是一个列表(可迭代对象),其实正如第 ...
- python 可迭代对象 迭代器 生成器总结
可迭代对象 只要有魔法方法__iter__的就是可迭代对象 list和tuple和dict都是可迭代对象 迭代器 只要有魔法方法__iter__和__next__的就是可迭代对象 生成器 只要含有y ...
- 【Python】【容器 | 迭代对象 | 迭代器 | 生成器 | 生成器表达式 | 协程 | 期物 | 任务】
Python 的 asyncio 类似于 C++ 的 Boost.Asio. 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyn ...
- Python--可迭代对象,迭代器,生成器
记得在刚开始学Python的时候,看到可迭代对象(iterable).迭代器(iterator)和生成器(generator)这三个名词时,完全懵逼了,根本就不知道是啥意识.现在以自己的理解来详解下这 ...
- 搞清楚 Python 的迭代器、可迭代对象、生成器
很多伙伴对 Python 的迭代器.可迭代对象.生成器这几个概念有点搞不清楚,我来说说我的理解,希望对需要的朋友有所帮助. 1 迭代器协议 迭代器协议是核心,搞懂了这个,上面的几个概念也就很好理解了. ...
- 11.Python初窥门径(函数名,可迭代对象,迭代器)
Python(函数名,可迭代对象,迭代器) 一.默认参数的坑 # 比较特殊,正常来说临时空间执行结束后应该删除,但在这里不是. def func(a,l=[]): l.append(a) return ...
- Python进阶(三)----函数名,作用域,名称空间,f-string,可迭代对象,迭代器
Python进阶(三)----函数名,作用域,名称空间,f-string,可迭代对象,迭代器 一丶关键字:global,nonlocal global 声明全局变量: 1. 可以在局部作用域声明一 ...
- python的可迭代对象
今日所得 迭代器 可迭代对象 迭代器对象 for循环内部原理 生成器 生成器表达式 内会函数 面对过程编程 迭代器 迭代就是指更新换代的过程,要重复进行,而且每次的迭代都必须基于上一次的结果. 我们使 ...
- python14 1.带参装饰器 | wrapper 了了解 # 2.迭代器 ***** # 可迭代对象 # 迭代器对象 # for迭代器 # 枚举对象
## 复习 '''函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.验证执行 开放封闭原则: 功能可以拓展,但源代码与调用方式都不可以改变 ...
随机推荐
- win10 为了对电脑进行保护,已经阻止此应用 解决方法
win10 为了对电脑进行保护,已经阻止此应用 解决方法 正确方法: ."win+x"进入控制面板,选择安全性与维护,在左侧更改windows smartscreen筛选器 ...
- Linux /bin, /sbin, /usr/bin, /usr/sbin 区别(转)
在linux下我们经常用到的四个应用程序的目录是:/bin./sbin./usr/bin./usr/sbin bin: bin为binary的简写主要放置一些系统的必备执行档例如:cat.cp ...
- 【Java】Java_03第一个Java程序
第一个JAVA程序的编写和运行 1.使用记事本编辑 public class Welcome{ public static void main(String[] agrs){ System.out.p ...
- sql中update,alter,modify,delete,drop的区别和使用(整理)
关于update和alter: 百度知道上关于update和alter有一个很形象的总结: 一个表有很多字段,一个字段里有很多数据. 一个家有很多房间,一个房间里有很多家具. update是用来将衣柜 ...
- php文件加载路径
<?php require('reusable.php'); echo "相对路径加载<br/>"; /* ./ 表示当前文件所在的目录 ../ 表示当前文件所在 ...
- python--web项目
zope:一个容器项目Plone:一个基于zope的工作流和内容管理项目trac:一个项目管理(任务指派.bug追踪项目,可以和subversion集成)moinmoin:一个强力的weiki系统
- rabbitMQ 基本概念
RabbitMQ 整体上是一个生产者与消费者模型,主要负责接收.存储和转发消息.可以把消 息传递的过程想象成:当你将一个包裹送到邮局,邮局会暂存并最终将邮件通过邮递员送到收件人的手上, RabbitM ...
- C# Enum,Int,String,之间及bool与int之间的转换
枚举类型的基类型是除 Char 外的任何整型,所以枚举类型的值是整型值. Enum 提供一些实用的静态方法: (1)比较枚举类的实例的方法 (2)将实例的值转换为其字符串表示形式的方法 (3)将数字的 ...
- php学习网站推荐
http://nikic.github.io/https://github.com/walu/phpbook http://www.chinaunix.net/ https://news.ycombi ...
- 无序列表li横向排列
一.横向两列方式排列: 在网页中,很多地方都会用到无序列表横向排列的形式,通常的写法都是使得li的css样式设置为:float:left的形式即可,li会依次从最左边开始并列对齐, 例如: HTML中 ...