理解可迭代对象
容器: 列表、字典、元组、集合等
都是将数据封装起来也供使用,只是它们各自的“安排方式”不同
容器可以被循环
for item in 容器:
这些可以被 for 循环的容器(对象)
我们就说它是可迭代的,
也就是可迭代对象,是 Iterable 的
isinstance() 函数来判断一个对象是否是一个已知的类型
可以通过 isinstance 来判断这个对象是否可迭代(Iterable)
1 | from collections import Iterable |
列表 True
字典 True
元组 True
字符串 True
整数 False
生成器 True
可以看到,除了整型对象外,其余对象、生成器均是可迭代对象
这些可迭代对象(Iterable)可以生成迭代器(Iterator)
迭代器的特点
当我们去使用迭代器的时候,
我们不用关心这个对象的长度,
不用关心容器里面是如何安排数据的。
迭代器之所以可迭代,
是因为它们提供了一个 next() 方法,
通过这个方法我们可以不断的去获取容器里面的下一个元素,
直到这个容器没有数据然后报 StopIteration 为止:
1 | list1 = [11, 22, 33, 44, 212] |
TypeError: ‘list’ object is not an iterator
这里列表是可迭代对象(Iterable),但还不是迭代器,因此不能使用 next() 方法
将列表转为迭代器(Iterator)要使用iter 魔法
1 | list1 = [11, 22, 33, 44, 212].__iter__() |
22
33
44
212
StopIteration
可以看到,我们这里调用 iter 魔法方法,
成功将列表(可迭代对象)变为 迭代器(Iterator), 从而使用 next 方法
可以通过 isinstance 来判断这个对象是否是迭代器(Iterator)
1 | from collections import 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 | list1 = iter(range(10)) |
<range_iterator object at 0x0293DCF8>
0
1
2
3
4
5
6
7
8
9
等价于:
1 | list1 = iter(range(10)) |
<range_iterator object at 0x0263DCF8>
0
1
2
3
4
5
6
7
8
9
5、生成器是一个迭代器。