[Python学习日记-43] Python 中的迭代器
简介
可迭代对象
迭代器
总结
简介
前面我们学习了各种各样的数据类型,在使用它们的时候我们也时不时会听到可迭代对象这一个名词,而本篇我们将讲述的迭代器感觉和我们之前学的可迭代对象挺相关的,那他们之间到底是什么关系呢?那又和我们之前讲过的生成器又是什么关系呢?下面我们来一起学习一下迭代器吧。
可迭代对象
我们已经知道,可以直接作用于 for 循环的数据类型有以下几种:
- 一类是集合数据类型,例如列表(list)、元组(tuple)、字典(dict)、集合(set)、字符串(str)等
- 一类是生成器(generator)和带 yield 的函数生成器(generator function)
这些可以直接作用于 for 循环的对象统称为可迭代对象(Iterable),可迭代的意思就是可遍历、可循环。可以使用 isinstance() 判断一个对象是否是 Iterable 对象,代码如下
注意:
- 在 Python 3.10 之前的版本可以使用以下方式来从 collections 库当中调取 Iterable 对象
from collections import Iterable
- 在 Python 3.10 之后的版本由于版本更新,原来的 collections 库下的 Iterable 对象已被取消,转而挪到了 collections.abc 下,Iterator 对象也是同样的状况,可以使用以下的方法进行调用
from collections.abc import Iterable
- 但由于 Python 3.10 前后都会被统称为 Python3,为避免不同版本之间会因为这个报错,我们在使用的时候可以做一些如下的差错处理
try:from collections.abc import Iterable
except ImportError:from collections import Iterable
- 该注意事项在 Iterator 对象当中也适用
而在写这篇文章的时候我们使用的是 Python 3.12.4 版本的,所以我们会用到 collections.abc,不过在代码中我们还是加入差错处理会比较稳健一些
try:from collections.abc import Iterable
except ImportError:from collections import Iterableprint(isinstance([], Iterable)) # 列表,True
print(isinstance({}, Iterable)) # 集合,True
print(isinstance("abc", Iterable)) # 字符串,True
print(isinstance((x for x in range(10)), Iterable)) # 生成器,True
print(isinstance(100, Iterable)) # 数字,False
代码输出如下:
迭代器
从上面的输出可以看出,生成器也是可迭代对象之一,不过生成器不但可以作用于 for 循环,还可以被 next() 函数不断调用并返回下一个值,直到最后抛出 Stoplteration 错误表示无法继续返
回下一个值了为止。而生成器就是迭代器之一了,我们把可以被 next() 函数调用并不断返回下一个值的对象称为迭代器(Iterator)。可以使用 isinstance() 判断一个对象是否是 Iterator,代码如下
try:from collections.abc import Iterator
except ImportError:from collections import Iteratorprint(isinstance((x for x in range(10)), Iterator)) # 生成器,True
print(isinstance([], Iterator)) # 列表,False
print(isinstance({}, Iterator)) # 集合,False
print(isinstance("abc", Iterator)) # 字符串,False
代码输出如下:
从输出可以看出生成器都是 Iterator 对象,但列表(list)、集合(set)、字符串(str)虽然是 Iterable,却不是 Iterator。但是我们可以使用 iter() 函数把列表(list)、集合(set)、字符串(str)这类 Iterable 变成 Iterator,代码如下
try:from collections.abc import Iterator
except ImportError:from collections import Iteratorprint(isinstance(iter([]), Iterator))
print(isinstance(iter({}), Iterator))
print(isinstance(iter("abc"), Iterator))
代码输出如下:
这里会有个疑问,为什么列表(list)、集合(set)、字符串(str)这类数据类型不是 Iterator 呢?这是因为 Python 的 Iterator 对象表示的是一个数据流,Iterator 对象可以被 next() 函数调用并不断返回下一个数据,直到没有数据时才抛出 StopIteration 错误。我们可以把这个数据流看作是一个有序序列,但我们却不能提前知道序列的长度,所以只能不断通过 next() 函数实现按需计算下一个数据,并且 Iterator 的计算是惰性的,只有在需要返回下一个数据时它才会计算。而列表(list)、集合(set)、字符串(str)这类数据类型从一开始数据长度就是确定的。总的来说,Iterator 甚至可以表示一个无限大的数据流,例如全体自然数。而使用列表(list)、集合(set)、字符串(str)这类数据类型是永远不可能存储全体自然数的。
总结
- 凡是可作用于 for 循环的对象都是 Iterable 类型
- 凡是可作用于 next() 函数的对象都是 Iterator 类型,它们表示一个惰性计算的序列
- 集合数据类型例如列表(list)、集合(set)、字符串(str)等是 Iterable 但不是 Iterator,不过可以通过 iter() 函数获得一个 Iterator 对象