三者联系
迭代器(iterator)是一个更抽象的概念,任何对象,如果它的类有next方法(next python3)和__iter__方法返回自己本身,即为迭代器
通常生成器是通过调用一个或多个yield表达式构成的函数s生成的。同时满足迭代器的定义。
生成器是一种特殊的迭代器,即生成器都是迭代器,但反过来不行。
生成器和迭代器都只能遍历一次,即对象迭代完后就不能重新迭代了。
可直接作用于for循环的数据类型:
集合数据类型,如list、tuple、dict、set、str等;
generator,包括生成器和带yield的generator function。
以上这些可以直接作用于for循环的对象统称为可迭代对象:Iterable
list、dict、str虽然是可迭代的,却不是迭代器:
这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
三者包含关系如下:
iterable->iterator->generator
生成器
分类(python有两种不同的方式提供生成器):
生成器函数:还是使用 def 定义函数,但是,使用yield而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。
-
生成器表达式:类似于列表推导,只不过是把一对大括号[]变换为一对小括号()。但是,生成器表达式是按需产生一个生成器结果对象,要想拿到每一个元素,就需要循环遍历。
即,可以简单地把列表生成式改成generator,也可以通过函数实现复杂逻辑的generator。
为什么要使用生成器:
因为效率。使用生成器表达式取代列表推导式可以同时节省 cpu 和 内存(RAM)。如果你构造一个列表(list)的目的仅仅是传递给别的函数,比如 传递给tuple()或者set(), 那就用生成器表达式替代吧!
使用生成器实例(代码往往极其简短,但较难理解)
利用生成器打印出杨辉三角(想打印多少打印多少,取决于n的定义)
def triangles():
L = [1]
while True:
yield L
L.append(0)
# 当i=0时,L[-1]代表列表最后一个元素(善于利用python切片特性!)
L = [L[i - 1] + L[i] for i in range(len(L))]
n = 0
for t in triangles():
print(t))
n = n + 1
if n == 10:
break