1、生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存的限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占有很大的存储空间,如果我们仅仅访问前面几个元素,那后面绝大元素占用的空间都白白浪费。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素?这样就不必须创建完整的list,从而节省大量的空间。在Python中,这样一边循环一边计算的机制,称为生成器:generator。
要创建一个generator有很多种方法。第一个方法很简单,只要把一个列表的[]改为(),就创建了一个generator:
>>> L = [x*x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x*x for x in range(10)) >>> g <generator object <genexpr> at 0x7fafe19d2410>
如果要一个一个打印出生成器的元素,可以通过next()函数获得:
>>> next(g) 0 >>> next(g) 1 >>> next(g) 4 >>> next(g) 9 >>> next(g) 16 >>> next(g) 25 >>> next(g) 36 >>> next(g) 49 >>> next(g) 64 >>> next(g) 81 >>> next(g) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
每次调用next(),就计算出g的下一个元素,知道计算到最后一个元素,没有更多元素,就会报错。
#!/usr/bin/env python g = (x*x for x in range(10)) for n in g: print(n) ==================================== 0 1 4 9 16 25 36 49 64 81
所以通常都是用for循环来迭代它。
裴波拉切数列用列表生成式写不出来,但是用函数可以:上面的函数和generato仅一步之遥
def fib(max): n, a, b = 0, 0, 1 while n < max: print(b) a, b = b, a + b n = n + 1 return 'done'
注意赋值语句:
a, b = b, a + b
相当于:
t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]
上面的函数和generato仅一步之遥,只需要把print(b)改为yield b就可以了
def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return 'done'
2、迭代器
2、迭代器
可以直接作用于for循环的对象统称为可迭代对象:Iterable。
可以使用Isinstance()判断一个对象是否为Iterable对象。
>>> from collections import Iterable >>> isinstance([],Iterable) True >>> isinstance({},Iterable) True >>> isinstance('abc',Iterable) True >>> isinstance(100,Iterable) False >>>
可以被next()函数调用并返回下一个值得对象称为迭代器:Iterator。
可以使用isinstance()判断一个对象是否是Iterator对象:
>>> from collections import Iterator >>> isinstance((x for x in range(10)),Iterator) True >>> isinstance([],Iterator) False >>> isinstance({},Iterator) False