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