生成器
生成器(generator)是迭代器的一种特殊实现方式,有2种方式可以创建,一种是通过生成器函数创建,另一种是生成器表达式进行创建。
生成器继承了迭代器的一切优点,简而言之是迭代器的一种升级版本。
在前面的迭代器一章节中介绍过,如果要想获取一个迭代器,必须要先创建一个可迭代对象,然后调用其下的__iter__()方法才能拿到一个迭代器,这样做会产生一些问题,如下所示:
- 我们只想要一个迭代器,并不需要可迭代对象的前提下该怎么办
- 可迭代对象中的数据项会占据大量内存空间,如果要想获取1个含有1000万个数据项的列表迭代器,则必须先创建1个列表对象,再获取其专属的迭代器,虽然迭代器不耗费内存,但是可迭代对象必然耗费内存
而生成器则是简化了这种操作,只需要创建生成器函数就可以拿到一个单纯的迭代器。
如果要判断一个对象是否属于生成器,推荐使用collections.abc下的Generator进行判定:
>>> from collections.abc import Generator
>>> isinstance(list,Generator)
False
生成器函数
如果一个函数中出现yield关键字,则它就是一个生成器函数,当一个生成器函数加括号进行调用时,并不会立即运行逻辑体代码,而是返回一个生成器对象。
当对这个生成器对象调用next()方法时,将启动该生成器对象,生成器对象开始执行函数逻辑体代码。
而在执行函数逻辑体代码时如果碰见yield则会发生2件事情:
- 返回yield后面的值,类似于return函数
- 挂起当前生成器函数的运行状态,而不是结束生成器函数的运行,也就是说这个生成器对象不会被销毁
再次对生成器对象调用next()方法时恢复暂停状态,继续上述流程进行运行。
一个简单的例子:
def generatorFunction():
n = 3
while n:
yield n
n-=1
# return None ❶
# ❷
generatorObject = generatorFunction()
print(generatorObject)
# ❸
print(next(generatorObject))
print(next(generatorObject))
print(next(generatorObject))
# ❹
print(next(generatorObject))
# <generator object generatorFunction at 0x10b5afdb0>
# 3
# 2
# 1
# StopIteration
❶:默认的函数返回值即为None,在Python3之前的较低版本中,return关键字和yield关键字不可以同时出现在一个函数中,但是目前已经取消了这种设定
❷:生成器函数加括号,返回生成器对象
❸:生成器对象调用next()方法,开始执行函数体代码
❹:由next()方法抛出的StopIteration异常ÿ