Python生成器和迭代器

时间:2022-08-03 18:40:50

 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'

Python生成器和迭代器


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