先上图
可迭代对象(Iterable)
对象中实现了 __getitem__ 或者 __iter__ 方法,那么这个对象就是可迭代对象;
可迭代对象分为两大类,一种是实际保存的序列,即列表、元组,字符串,Python中几乎所有的容器类型都是可迭代对象;另一种是虚拟序列,包括range函数的返回值、zip函数的返回值、enumerate函数的返回值等等。
迭代器(Iterator)
若对象中实现了 __next__ 和 __iter__ 方法,那么这个对象就是迭代器;
可迭代对象支持内置函数iter,通过对可迭代对象调用iter函数,会返回一个迭代器,而“迭代器”支持内置函数next,通过不断对其调用next方法,会依次前进到序列中的下一个元素并将其返回,最后到达一系列结果的末尾时,会引发StopIteration异常。
对于可迭代对象,使用iter()方法,可以返回一个迭代器,然后可以通过next()函数每次取一个值出来,如:
L = [1, 2, 3, 4]
L_iter = iter(L)
print(next(L_iter)) # 1
print(next(L_iter)) # 2
PS:for循环遍历链表的时候,解释器帮助我们对列表调用了iter()方法,将其转换成迭代器,然后每次使用next()取一个值出来。
生成器(Generator)
生成器可以理解为是一种特殊的迭代器,和迭代器在一般情况下没有区别,它是用生产器函数那种语法,来得到的一个迭代器。
它和迭代器的主要区别在于,生成器并不是一上来就把所有值装载进内存,因而也不会占用大量的内存,只是在需要使用next()函数获取值的时候,才会取一个值返回,内存开销非常小;所以,生成器对象更倾向于在无限大集合中惰性的输出需要的数据(如斐波那契数列),而迭代器更倾向于在实现已知道所有数据的情况下惰性输出需要的数据。
python3中最简单的形式是生成器表达式(Generator Expression),它有点像列表推导式:
# 注意这里用的是小括号而不是中括号
gen = (i for i in range(10000))
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
还有一种常见的写法就是在函数中使用yield返回一个生成器,这种函数就是Generator function:
def fib():
prev, curr = 0, 1
while True:
yield curr
curr, prev = prev + curr, curr
f = fib()
for i in range(10):
print(next(f))
输出:
1
1
2
3
5
8
13
21
34
55
上面的 fib 函数中没有 return 关键字。当运行 f = fib() 的时候,它返回的是一个生成器对象。在调用 fib() 的时候并不会运行 fib 函数中的代码,只有在调用 next() 的时候才会真正运行其中的代码。使用生成器,函数不用一次性生成所有的元素,只需在每次调用next的时候生成元素,这样更节省内存和CPU