以下段落是本书的确切引文
从头开始编写可迭代项和迭代器可能有点乏味,因此Python提供了生成器来简化可迭代序列的创建。生成器是通过调用包含yield语句的函数产生的。执行这样的函数不会调用函数的主体,而是返回一个生成器对象。这是一个生成器,它产生连续的2的幂,直到某个极限:
def powers_of_two(limit):
value = 1
while value < limit:
yield value
value += value
# Use the generator
for i in powers_of_two(70):
print(i)
1
2
4
8
16
32
64
下面的两行函数无需使用生成器即可完成完全相同的操作,并且肯定不会像作者建议的那样“乏味”。
def alternative_powers_of_two(limit):
for i in range(int(math.log(limit,2)+1)):
print(2**i)
那么这个生成器东西的价值是什么?与其简化编写迭代器,不如说完全相反-至少在作者使用的示例中。
答案 0 :(得分:3)
对于初学者,我们需要定义iterable
,iterator
和generator
。
iterable
是具有__iter__
方法并返回iterator
或定义__getitem__
方法的对象,该方法采用顺序索引(从0开始),并返回某个对象(或引发IndexError
)。iterator
是具有next
(Python 2)或__next__
(Python 3)方法的对象,这些方法在每次调用时返回序列中的下一个对象或引发{ {1}}。这样说,我们可以说“每个迭代器都是可迭代的,但并非每个迭代器都是迭代器”。StopIteration
是一个“惰性迭代器”,它“承诺”在下一次调用时返回值,而不为这些序列分配任何内存。这样说,我们可以说“每个生成器都是一个迭代器,但并不是每个迭代器都是一个生成器”。关于“便利”的陈述,请考虑一个例子:
generator
作为发电机,同样的事情
class MyAwesomeIterator(object):
def __init__(self, limit):
self.idx = 0
self.limit = limit
def __iter__(self): return self
def next(self):
if self.idx >= self.limit:
raise StopIteration
current = 2**self.idx
self.idx += 1
return current
或更短(genexp):
def MyAwesomeGenerator(limit):
for idx in range(limit):
yield 2**idx