什么是Python的可迭代对象迭代器

理解可迭代对象

容器: 列表、字典、元组、集合等
都是将数据封装起来也供使用,只是它们各自的“安排方式”不同

容器可以被循环

for item in 容器:

这些可以被 for 循环的容器(对象)
我们就说它是可迭代的,
也就是可迭代对象,是 Iterable 的

isinstance() 函数来判断一个对象是否是一个已知的类型
可以通过 isinstance 来判断这个对象是否可迭代(Iterable)

1
2
3
4
5
6
7
8
from collections import Iterable

print('列表', isinstance([], Iterable))
print('字典', isinstance({}, Iterable))
print('元组', isinstance((), Iterable))
print('字符串', isinstance('', Iterable))
print('整数', isinstance(66, Iterable))
print('生成器', isinstance((i for i in range(10)), Iterable))

列表 True
字典 True
元组 True
字符串 True
整数 False
生成器 True

可以看到,除了整型对象外,其余对象、生成器均是可迭代对象

这些可迭代对象(Iterable)可以生成迭代器(Iterator)

迭代器的特点

当我们去使用迭代器的时候,
我们不用关心这个对象的长度,
不用关心容器里面是如何安排数据的。

迭代器之所以可迭代,
是因为它们提供了一个 next() 方法,
通过这个方法我们可以不断的去获取容器里面的下一个元素,
直到这个容器没有数据然后报 StopIteration 为止:

1
2
list1 = [11, 22, 33, 44, 212]
print(next(list1))

TypeError: ‘list’ object is not an iterator

这里列表是可迭代对象(Iterable),但还不是迭代器,因此不能使用 next() 方法
将列表转为迭代器(Iterator)要使用iter 魔法

1
2
3
4
5
6
7
list1 = [11, 22, 33, 44, 212].__iter__()
print(next(list1))
print(next(list1))
print(next(list1))
print(next(list1))
print(next(list1))
print(next(list1))

22
33
44
212
StopIteration

可以看到,我们这里调用 iter 魔法方法,
成功将列表(可迭代对象)变为 迭代器(Iterator), 从而使用 next 方法

可以通过 isinstance 来判断这个对象是否是迭代器(Iterator)

1
2
3
4
5
6
7
from collections import Iterator
print('列表', isinstance(iter([]), Iterator))
print('字典', isinstance(iter({}), Iterator))
print('元组', isinstance(iter(()), Iterator))
print('字符串', isinstance(iter(''), Iterator))
print('整数', isinstance(66, Iterator))
print('生成器', isinstance((i for i in range(10)), Iterator))

列表 True
字典 True
元组 True
字符串 True
整数 False
生成器 True

从以上输出结果可以看出
生成器本身也是迭代器(iterator)
所以不用 iter 魔法转换,
生成器继可以用 next 不断迭代,也可以使用 for 循环。

只有可迭代对象才能用 iter 魔法转换为 迭代器(iterator)
所以下列代码中 iter(66)报措

1
print('整数', isinstance(iter(66), Iterator))

TypeError: ‘int’ object is not iterable

总结
到这里你应该明白这么几点:

1、迭代和我们一般所认为的遍历枚举的差别在于:
迭代是不需要知道容器的“容量”的,
每次访问都可以获取到下一个元素,直到没有为止。
就好像你去 Apple 官网买 iPhone 一样,
你不需要他们罗列出了多少台手机,
你可以一直买,
每次他都给你发手机,
直到没货了,
他才会跟你说不好意思,库存不足。(StopIteration)停止迭代

2、可迭代对象不可以使用 next() 方法,迭代器才可以,
如何成为迭代器呢?使用 iter 方法。

3、迭代器是在每次获取才去计算下一个元素的,
所以它降低不必要的内存浪费,也可以存储一些 “理想” 的数据,
比如可以存储根据一定规律的无穷个数字:“2,4,6,8,10…….10000000000000(无穷)”,
但是用一般的列表来存储的话,根本不可能,内存早就爆炸了。

4、 for i in 迭代器的过程中,实际上就是再不断的调用 next():

1
2
3
4
5
list1 = iter(range(10))
print(list1)

for item in list1:
print(item)

<range_iterator object at 0x0293DCF8>
0
1
2
3
4
5
6
7
8
9

等价于:

1
2
3
4
5
6
7
8
list1 = iter(range(10))
print(list1)

while True:
try:
print(next(list1))
except StopIteration: # 没有数据了
break

<range_iterator object at 0x0263DCF8>
0
1
2
3
4
5
6
7
8
9

5、生成器是一个迭代器。