我们有时候需要一个可迭代对象。比如列表,但遇到海量数据时往往非常耗内存,费空间,这时不妨考虑使用生成器。
生成器是迭代器,只能遍历一次,返回一个生成器对象。特点:按需计算,惰性求值。
定义生成器的表达式:
g = (i for i in range(10)) >>> g <generator object <genexpr> at 0x00000200BFA71570>
用next()
函数可以不断获得下一个返回值,generator保存的是算法,每次调用next(g)
,就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration
的错误。
通常我们创建了一个generator后,基本上永远不会调用next()
,而是通过for
循环来迭代它,并且不需要关心StopIteration
的错误。
当生成器表达式无法实现复杂算法时,可以定义函数:
def inc(): for i in range(5): yield i 等价于 def inc(): yield from range(1000) # yield from iterable 是 for item in iterable: yield item 的语法糖
如果一个函数定义中包含yield
关键字,那么这个函数就不再是一个普通函数,而是一个generator,可用于迭代。
yield
是一个类似return
的关键字,迭代一次遇到yield
时就返回yield
右边的值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始。
案例
def inc(): for i in range(5): yield i print(type(inc) x = inc() print(x) print(type(x)) print(next(x)) for m in x: print(m, '*') for m in x: print(m, '**') 运行结果: <class 'function'> <generator object inc at 0x0000024F97ED15C8> <class 'generator'> 0 1 * 2 * 3 * 4 * 可以看出返回一个对象,并且只能遍历一次。