一.简单生成器特性
查询了官方文档(见参考资料[1]),主要有以下几个概念:
generator:
返回一个 generator iterator 的函数。它看上去很像普通的函数,只是它包含
yield
表达式用于生成一系列的值,这些值可以用于 for 循环或通过next()
函数一次一个地取出来。通常是指一个 generator 函数,但在某些上下文中可能是指一个 generator iterator。如果意欲达到的含义不明确,则使用完整术语可避免含糊不清。(注:即我们常说的生成器函数)
generator iterator:
由一个 generator 函数创建的对象。
每个
yield
临时挂起当前的运行,记住执行的位置和状态(包括局部变量和等待的 try 语句)。当 generator iterator 恢复时,它从离开的位置重新开始(与函数不同,函数每次调用从起始开始)。(注:我们常说的生成器对象)
generator expression:
一个返回 iterator 的表达式。它看起来像一个普通的表达式后跟一个定义循环变量的
for
表达式、range和一个可选的if
表达式。这个组合表达式为闭包函数生成值(注:我们常说的生成器表达式):>>> sum(i*i for i in range(10)) # sum of squares 0, 1, 4, ... 81 285
解释:
挂起,返回出中间值,并多次继续的协同程序成为生成器(从语法上讲,生成器是一个带yield关键字的函数)。与迭代器的—__next__()似,迭代器使用yield关键字,当遇到yield关键字时,先返回一个值给调用者,然后“暂停”代码的执行。当被生成器的next()方法调用时,它会准确的从离开的地方继续,如果没有值可以访问,那么就会抛出StopIteration——由于Python的for 循环有next()调用和对StopIteration处理,所以使用for循环而不是手动调用生成器更优雅一些。
# -*- coding:utf-8 -*-
from collections.abc import Iterator
def my_generator():
yield 1
yield 2
mg = my_generator()
print(mg) # 生成器函数返回一个生成器对象: <generator object my_generator at 0x00000225C64BC480>
# 可以使用next()调用生成器,但是会引发StopIteration异常
# print(next(mg)) # 1
# print(next(mg)) # 2
# print(next(mg)) # StopIteration
# 使用for循环比较优雅,自动处理StopIteration
for i in mg:
print(i) # 1 2
列表解析生成一个list,同时暂用内存。而生成器表达式返回一个迭代器,采用的时延迟计算,占用内存更小。
二.加强的生成器特性
生成器除了可使用next()获取下一个值,还可以将值返回给生成器[send()],在生成器中抛出异常[throw()],以及要生成器退出[close()]。
>>> def counter(start_at=0):
... count = start_at
... while True:
... val = (yield count)
... if val is not None:
... count = val
... else:
... count += 1
...
>>> count = counter(5)
>>> next(count)
5
>>> count.send(9)
9
>>> next(count)
10
>>> count.close()
>>> next(count)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
三.总结
总结引用kissg.me博客的内容,见参考资料[2]。
-
可迭代对象(Iterable)是实现了
__iter__()
方法的对象,通过调用iter()
方法可以获得一个迭代器(Iterator) -
迭代器(Iterator)是实现了
__iter__()
和__next__()
的对象 -
for ... in ...
的迭代,实际是将可迭代对象转换成迭代器,再重复调用next()
方法实现的 -
生成器(generator)是一个特殊的迭代器,它的实现更简单优雅.
-
yield
是生成器实现__next__()
方法的关键.它作为生成器执行的暂停恢复点,可以对yield
表达式进行赋值,也可以将yield
表达式的值返回.
四.参考资料
[1]python官方文档generator:https://docs.python.org/3/glossary.html#term-generator
[2]Python之生成器详解:http://kissg.me/2016/04/09/python-generator-yield/#generator
[3]Python官方文档Generator-iterator methods:https://docs.python.org/3/reference/expressions.html#generator-iterator-methods
[4]yield表达式:https://docs.python.org/3/reference/expressions.html#yield-expressions