一、概要
在了解Python的数据结构时,容器(container)、可迭代对象(iterable)、迭代器(iterator)、生成器(generator)、列表/集合/字典推导式(list,set,dict comprehension)众多概念参杂在一起,难免让人一头雾水,下面这幅图也许能让大家更清楚的理解他们之间的关系。
二、容器(container)
容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用 in , not in 关键字判断元素是否包含在容器中。通常这类数据结构把所有的元素存储在内存中(也有一些特列并不是所有的元素都放在内存)在Python中,常见的容器对象有:
- list
- dict
- set
- tuple
- str
尽管绝大多数容器都提供了某种方式来获取其中的每一个元素,但这并不是容器本身提供的能力,而是可迭代对象赋予了容器这种能力,当然并不是所有的容器都是可迭代的。
三、可迭代对象(iterable)
一个list或tuple,我们可以通过for
循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)。很多容器都是可迭代对象(比如:list、dict、tuple等),此外,像打开的文件,也是可迭代对象。但凡可以返回一个迭代器的对象都可成为可迭代对象。
这里x是一个list,是一个可迭代对象。我们知道,list、dict、set、tuple、str都是可迭代对象,通过iter()或__iter__(),就可以转化为一个迭代器。所以,我们可以说:一个具有iter方法的对象就可以称为可迭代对象。
四、迭代器(iterator)
上图中,y和z就是两个独立的迭代器,它是通过iter()方法从可迭代对象转化而来的。它是一个带状态的对象,该状态用于记录当前迭代所在的位置,以便下次迭代的时候取到正确的元素。它能在你调用 next() 方法的时候返回容器中的下一个值,任何实现了 __next__() 或next()方法的对象都是迭代器。迭代器有一种具体的迭代器类型,比如 list_iterator、set_iterator、tuple_iterator、str_iterator等 。
五、for循环的内部实现
在大多数情况下我们都不会用next()方法去可迭代对象中去取值,而是会用:for i in (iterable),如下图:
for循环内部做了3件事情:
- 调用iter()把可迭代对象转换成迭代器
- 不断的调用迭代器的next()方法
- 处理StopIteration异常,结束循环
六、isinstance
可以使用isinstance()
判断一个对象是否是Iterator
对象,如下:
1 from collections import Iterator,Iterable 2 l = [1,2,3,4,5] 3 d = iter(l) 4 print(isinstance(l,list)) # 判断是否是list 5 print(isinstance(l,Iterable)) # 判断是否是可迭代对象 6 print(isinstance(l,Iterator)) # 判断是否是迭代器 7 print(isinstance(d,Iterator)) # 判断是否是迭代器 8 # True 9 # True 10 # False 11 # True