1 简介
list,tuple,dict,set都是容器,容器是可迭代对象,可迭代对象通过调用iter()函数可以得到一个迭代器。
迭代器可以通过next()函数来得到下一个元素,从而支持遍历。
生成器,迭代器,可迭代对象,容器,他们之间的关系。图片来自https://nvie.com/posts/iterators-vs-generators/
参考https://zhuanlan.zhihu.com/p/26123333
2 可迭代对象(iterable)
可直接作用于for循环的对象统称为Iterable,具体的实现是,Python 中的对象只要定义了__iter__方法(该方法返回一个迭代器对象)就是可迭代对象。
容器,list,tuple,dict,set是可迭代对象,是迭代器吗?
from collections import Iterable,Iterator
items = [123,"123",[1,2,3],(1,2,3),{"a":1,"b":2},{1,2,3}]
for item in items:
temp = "{0}的类型是{1},它是可迭代对象:{2},它是迭代器:{3}".format(item,type(item),isinstance(item,Iterable),isinstance(item,Iterator))
temp2 = "实现了__iter__方法{0}".format("__iter__" in dir(item))
print(temp,"\n")
print(temp2, "\n")
结果
123的类型是<class 'int'>,它是可迭代对象:False,它是迭代器:False
实现了__iter__方法False
123的类型是<class 'str'>,它是可迭代对象:True,它是迭代器:False
实现了__iter__方法True
[1, 2, 3]的类型是<class 'list'>,它是可迭代对象:True,它是迭代器:False
实现了__iter__方法True
(1, 2, 3)的类型是<class 'tuple'>,它是可迭代对象:True,它是迭代器:False
实现了__iter__方法True
{'a': 1, 'b': 2}的类型是<class 'dict'>,它是可迭代对象:True,它是迭代器:False
实现了__iter__方法True
{1, 2, 3}的类型是<class 'set'>,它是可迭代对象:True,它是迭代器:False
实现了__iter__方法True
str,list,tuple,dict,set是可迭代对象,不是迭代器,没有实现__iter__方法
3 迭代器(iterator)
由上面可知str,list,tuple,dict,set是可迭代对象,不是迭代器
字符串,列表可以通过索引来去除元素,而集合没有索引,想取出其中的元素,就是不依赖于索引的方式,也就是迭代器。
可作用于next()函数的对象都是Iterator。具体的实现是,任何对象只要定义了__iter__和__next__方法,那就是迭代器对象
创建迭代器
lis = [1,2,3,4]
lis2 = iter(lis)
print(type(lis2))
print("__next__" in dir(lis))
print("__next__" in dir(lis2))
结果
<class 'list_iterator'>
False
True
所以str,list,tuple,dict,set通过调用iter()函数就创建了迭代器,实现了__iter__和__next__方法
可迭代对象与迭代器的区别:
- 迭代器实现了__iter__和__next__方法
- 可迭代对象只实现了__iter__方法,没有实__next__方法
4 生成器(generator)
生成器就是一种特殊的迭代器,不过它的实现方式更为简单优雅,同样我们可以明确的是,任何生成器都是迭代器
生成器是懒人方式的迭代器。
在迭代器中,如果要枚举它的元素,这些元素需要提前生成。试想,如果元素有1千万,是不是比较占内存。生成器中的元素没有提前生成好,而是通过调用next()函数来生成下一个元素。
创建生成器的方式:
- 通过小括号()
- 通过yield关键字
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。调用一个生成器函数,返回的是一个迭代器对象。
来自https://www.runoob.com/python3/python3-iterator-generator.html
5 总结
字符串和容器(列表,元组,字典,集合)是可迭代对象,它实现了__iter__方法,
通过调用iter()方法创建了迭代器,迭代器实现了__iter__和__next__方法,
生成器是特殊的迭代器,它的元素在调用next()函数时才生成,与迭代器比,节省内存。