迭代器与生成器

 迭代器, 生成器

  • 练习: 说出如下代码的打印结果

     
      >>> def foo():
      ...    print(111)
      ...    yield 222
      ...    print(333)
      ...    yield 444
      ...    print(555)
      >>> n = foo()
      >>> next(n)
      >>> next(n)
      >>> next(n)
     
  • generator: 生成器是一种特殊的迭代器, 不需要自定义 __iter____next__

    • 生成器函数 (yield)

    • 生成器表达式

class Range:
    def __init__(self, start, end=None, step=1):
        if end is None:
            self.end = start
            self.start = 0
        else:
            self.start = start
            self.end = end
        self.step = step
    def __iter__(self):
        return self
    def __next__(self):
        if self.start < self.end:
            current = self.start
            self.start += self.step
            return current
        else:
            raise StopIteration()
 
  • iterator: 任何实现了 __iter____next__ 方法的对象都是迭代器.

    • __iter__ 得到一个迭代器。迭代器的__iter__()返回自身

    • __next__ 返回迭代器下一个值

    • 如果容器中没有更多元素, 则抛出 StopIteration 异常

    • Python2中没有 __next__(), 而是 next()

  • str / bytes / list / tuple / dict / set 自身不是迭代器,他们自身不具备 __next__(), 但是具有 __iter__(), __iter__() 方法用来把自身转换成一个迭代器

  • 练习1: 定义一个随机数迭代器, 随机范围为 [1, 50], 最大迭代次数 30

      import random
      class RandomIter:
          def __init__(self, start, end, times):
              self.start = start
              self.end = end
              self.count = times
          def __iter__(self):
              return self
          def __next__(self):
              self.count -= 1
              if self.count >= 0:
                  return random.randint(self.start, self.end)
              else:
                  raise StopIteration()
     
  • 练习2: 自定义一个迭代器, 实现斐波那契数列

     
      class Fib:
          def __init__(self, max_value):
              self.prev = 0
              self.curr = 1
              self.max_value = max_value
          def __iter__(self):
              return self
          def __next__(self):
              if self.curr <= self.max_value:
                  res = self.curr
                  self.prev, self.curr = self.curr, self.prev + self.curr  # 为下一次做准备
                  return res
              else:
                  raise StopIteration()
     
  • 练习3: 自定义一个生成器函数, 实现斐波那契数列

      def fib(max_value):
          prev = 0
          curr = 1
          while curr < max_value:
              yield curr
              prev, curr = curr, curr + prev
     
  • 迭代器、生成器有什么好处?

    • 节省内存

    • 惰性求值 (惰性求值思想来自于 Lisp 语言)

  • 各种推导式

    • 分三部分:生成值的表达式, 循环主体, 过滤条件表达式

    • 列表: [i * 3 for i in range(5) if i % 2 == 0]

    • 字典: {i: i + 3 for i in range(5)}

    • 集合: {i for i in range(5)}

原文地址:https://www.cnblogs.com/gugubeng/p/9755226.html