Python中的可迭代对象,迭代器与生成器
先来看一张概览图,关于容器(container)、可迭代对象(Iterable)、迭代器(iterator)、生成器(generator)。
一、容器(container)
容器就是一个用来存储多个元素的数据结构,常见的容器包括【列表】、【元组】、【字典】、【集合】、【字符串】。
容器有两个特点:1. 容器中的元素可通过迭代获取 2. 所有容器中的元素被存储在内存中。
二、可迭代对象(Iterable)
可迭代对象,简单的说就是可以被迭代获取的对象,iterable定义了可返回迭代器的__iter__方法。
通过使用iter()方法,我们能将可迭代对象返回成迭代器。例如列表:
from collections import Iterable
# 定义一个列表,其本身是可迭代对象
list_a = ['a', 'b', 'c']
isinstance(list_a, Iterable) # True
new_a = iter(list_a) # 对迭代器调用next()方法
>>> next(new_a)
a
>>> next(new_a)
b
>>> next(new_a)
c
>>> next(new_a) # 抛出StopIteration异常
三、迭代器(Iterator)
迭代器是一个带状态的对象,迭代器内部持有一个状态,该状态用于记录当前迭代所在位置,以便于下次迭代的时候获取正确
的元素。迭代器可以通过next()方法来迭代获取下一个值。
迭代器实现了__iter__() 和 __next__()方法。而且,迭代器不会一次性吧所有元素都加载到内存,而是需要的时候才返回结果。
from collections import Iterable
# 定义一个列表,其本身是可迭代对象
list_a = ['a', 'b', 'c']
isinstance(list_a, Iterable) # True
new_a = iter(list_a) # 对迭代器调用next()方法
>>> next(new_a)
a
>>> next(new_a)
b
>>> next(new_a)
c
>>> next(new_a) # 抛出StopIteration异常
迭代器每次调用next()方法的时候做两件事:1. 为下一次调用next()方法修改状态 2. 生成当前调用的返回结果。
当我们第一次调用next(new_a)之后,当前状态改为即指向a,且输出a,当我们第二次调用的时候,输出b,并且将
当前状态改为指向b...
四、生成器
生成器是一种特殊的迭代器。特殊在我们可以通过send()方法像生成器中传入数据,而迭代器只能将数据输出。
其主要的特点有:
1、生成器拥有迭代器的迭代传出数据的功能,但用关键字yield来替代迭代器中的__next__()方法来实现,而拥有yield关键字的函数
就是生成器函数。
2、生成器可以传入数据进行计算(不同于迭代器),并根据变量内容计算结果后返回。
3、迭代器不会一次把所有的元素加载到内存,而是调用的时候才生成返回结果(这点相同于迭代器)
4、可以通过for循环进行迭代(因为生成器是迭代器)
总结:生成器是一种特殊的迭代器,其具有传入数据的功能。
下面借助一个简短的程序来具体解释一下yield执行过程:
def generator_1():
y = 0
r = 'here'
while True:
x = yield r g_1 = generator_1()
g_1.send(None)
g_1.send(1)
g_1.send(2)
首先我们写了一个很简单的生成器函数,然后我们定义了一个生成器对象g_1,当我们启动生成器的时候第一个send()只能传入None
为什么只能是None呢,我们来看其具体执行过程,从函数的第一行开始执行,然后一直到 x = yield r,根据从右向左执行的原则,首先
执行yield r 然后程序终止,并没有赋值语句,因此,第一个send()只能传入None。当第二次send()时,从上一次中断的地方开始执行,
上一次是中断在了赋值,那么我们开始从赋值执行,即 x = 1...后边的类似。
参考:https://blog.csdn.net/SL_World/article/details/86507872 作者:SL_World
最新文章
- 使用VideoToolbox硬编码H.264<;转>;
- css3 --- 翻页动画 --- javascript --- 3d --- Action
- iOS 小知识-tips
- svn 项目转移
- 委托的lambda表达式
- slide from one widget to another
- QT中QProcess调用命令行的痛苦经历(调用Winrar,设置工作目录,获得输出,注意引号与括号,等等)
- IDEA github的应用
- Android消息机制解析
- Jenkins时区设置为北京时间
- 68.jq---tab选项实现网页定点切换
- c/c++ 通用的(泛型)算法 generic algorithm 总览
- spring 生命周期最详解
- jQuery事件委托
- 从工程化角度讨论如何快速构建可靠React组件
- 主机无法访问虚拟机的apache解决办法
- boost--smart_ptr库
- 细数用anaconda安装mayavi时出现的各种问题
- [AngularJS] Angular 1.3 Anuglar hint
- 移动端与PHP服务端接口通信流程设计(基础版)