Python 生成器和迭代器
1. 生成器
- 通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个
包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数
的元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的
过程中不断推算出后续的元素呢?这样,就不必创建完整的list,从而节省大量的空间。 - 在Python中,这种一边循环一边计算的机制,称为生成器(generator)
# 列表生成式,值一下子,全部计算出来:
L = [ x*2 for x in range(5)]
L # 输出: [0, 2, 4, 6, 8]
# 创建生成器, 列表元素是推算出来的:
G = ( x*2 for x in range(5))
G # 输出: <generator object <genexpr> at 0x1077d9db0>
next(G) # 每执行一次 next(),输出一个元素, 等价于 G.__next__(), Python 2.x : G.next()
# 创建生成器的第二种方式: 使用函数(yield 关键字)
# 斐波拉契数列(Fibonacci)
def fib(times):
n = 0
a, b = 0, 1
while n < times:
print(b)
a, b = b, a+b
n += 1
return 'done'
fib(5)
# 生成器(ipython 中操作)
def fib():
print("=== start ===")
a, b = 0, 1
for i in range(5):
print("=== 1 ===")
yield b
print("=== 2 ===")
a, b = b, a+b
print("=== 3 ===")
print("=== stop ===")
a = fib()
a # 输出: <generator object fib at 0x23355>
next(a) # 等价于 a.__next__()
# 输出:
# === start ===
# === 1 ===
# 1
# 此时,fib()函数就是生成器,可以使用循环来迭代
for num in a:
print(num)
1.1 send 方法
# 示例:
# ipython3 中操作
def gen():
i = 0
while i<5:
temp = yield i
print(temp)
i+=1
a = gen()
a.__next__() # 输出: 0
a.__next__() # 输出: None
c = a.send("haha") # 输出: haha
print(c) # 输出: 2
# 说明: 程序执行到yield时,gen函数暂时停止,同时返回i的值;
# temp 接收send过来的值(haha);
# a.__next__() 等价 a.send(None)
# 若是第一次直接调用 a.send("haha"), 程序会报错
2. 迭代器
- 迭代是访问集合元素的一种方式。
- 迭代器是一个可以记住遍历的位置的对象;
- 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束;
- 迭代器只能往前不会后退;
2.1 可迭代对象
- 可以直接作用于 for 循环的数据类型有以下几种:
- 集合数据类型:
list
,tuple
,dict
,set
,str
等; generator
, 包括生成器和带yield
的generation function
;- 这些可以直接作用于for循环的对象统称为可迭代对象(Iterable)
- 集合数据类型:
- 可以使用
isinstance()
判断一个对象是否是Iterable
对象; - 拥有内置方法
__iter__()
;
# 示例:
from collections import Iterable
isinstance([], Iterable) # True
2.2 迭代器
- 可以被
next()
函数调用并不断返回下一个值的对象称为迭代器(Iterator); - 可以使用
isinstance()
判断一个对象是否是 Iterator 对象;
# 示例:
from collections import Iterator
isinstance((x for x in range(10), Iterator) # True
isinstance([], Iterator) # False
2.3 iter()函数
- 生成器都是 Iterator 对象;
list
,dict
,str
虽然是 Iterable,却不是 Iterator;- 可以使用
iter()
函数把list
,dict
,str
等 Iterable 变成 Iterator;
# 示例:
from collections import Iterator
isinstance(iter([]), Iterator) # True
参考资料: