python生成器真正完成什么工作?

时间:2018-11-06 23:49:43

标签: python generator

以下段落是本书的确切引文

https://www.amazon.com/Programming-Language-Explorations-Ray-Toal/dp/149873846X/ref=sr_1_fkmr1_1?s=books&ie=UTF8&qid=1541545240&sr=1-1-fkmr1&keywords=Programming+Language+Explorati+1st+Edition

从头开始编写可迭代项和迭代器可能有点乏味,因此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)

那么这个生成器东西的价值是什么?与其简化编写迭代器,不如说完全相反-至少在作者使用的示例中。

1 个答案:

答案 0 :(得分:3)

对于初学者,我们需要定义iterableiteratorgenerator

  • Python中的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