Python笔记:迭代器和生成器

本笔记整理自 udacity 课程,版权归 udacity 所有, 更多信息请访问 Udacity

迭代器和生成器

  • 迭代器

    • 每次可以返回一个对象元素的对象,例如返回一个列表。我们到目前为止使用的很多内置函数(例如 enumerate)都会返回一个迭代器。
    • 是一种表示数据流的对象。这与列表不同,列表是可迭代对象,但不是迭代器,因为它不是数据流。
  • 生成器

    • 是使用函数创建迭代器的简单方式。也可以使用类定义迭代器
    • 下面是一个叫做 my_range 的生成器函数,它会生成一个从 0 到 (x - 1) 的数字流:

      def my_range(x):
        i = 0
        while i < x:
            yield i
            i += 1
    • 该函数使用了 yield 而不是关键字 return。这样使函数能够一次返回一个值,并且每次被调用时都从停下的位置继续。关键字 yield 是将生成器与普通函数区分开来的依据。

    • 因为上述代码会返回一个迭代器,因此我们可以将其转换为列表或用 for 循环遍历它,以查看其内容。例如,下面的代码:

      for x in my_range(5):
        print(x)
    • 输出如下:

      0
      1
      2
      3
      4
  • 为何要使用生成器?

    • 生成器是构建迭代器的 “懒惰” 方式。当内存不够存储完整实现的列表时,或者计算每个列表元素的代价很高,你希望尽量推迟计算时,就可以使用生成器。但是这些元素只能遍历一次。
    • 由于使用生成器是一次处理一个数据,在内存和存储的需求上会比使用list方式直接全部生成再存储节省很多资源。由此区别,在处理大量数据时,经常使用生成器初步处理数据后,再进行长期存储,而不是使用 list。
    • 因为无论使用生成器还是 list,都是使用过就要丢弃的临时数据。既然功能和结果一样,那就不如用生成器。
    • 但是生成器也有自己的局限,它产生的数据不能回溯,不像list可以任意选择。

迭代器和生成器[相关练习]

  • 请自己写一个效果和内置函数 enumerate 一样的生成器函数。如下所示地调用该函数:

    lessons = ["Why Python Programming", "Data Types and Operators", "Control Flow", "Functions", "Scripting"]
    
    for i, lesson in my_enumerate(lessons, 1):
        print("Lesson {}: {}".format(i, lesson))
    

    应该会输出:

    Lesson 1: Why Python Programming
    Lesson 2: Data Types and Operators
    Lesson 3: Control Flow
    Lesson 4: Functions
    Lesson 5: Scripting

    解决方案:

    lessons = ["Why Python Programming", "Data Types and Operators", "Control Flow", "Functions", "Scripting"]
    
    def my_enumerate(iterable, start=0):
        # Implement your generator function here
        i = start
        for element in iterable:
            yield i, element
            i += 1
    
    for i, lesson in my_enumerate(lessons, 1):
        print("Lesson {}: {}".format(i, lesson))
  • 如果可迭代对象太大,无法完整地存储在内存中(例如处理大型文件时),每次能够使用一部分很有用。实现一个生成器函数 chunker,接受一个可迭代对象并每次生成指定大小的部分数据。如下所示地调用该函数:

    for chunk in chunker(range(25), 4):
      print(list(chunk))

    应该会输出:

    [0, 1, 2, 3]
    [4, 5, 6, 7]
    [8, 9, 10, 11]
    [12, 13, 14, 15]
    [16, 17, 18, 19]
    [20, 21, 22, 23]
    [24]

    解决方案:

    def chunker(iterable, size):
      for i in range(0, len(iterable), size):
          yield iterable[i:i + size]
    
    for chunk in chunker(range(25), 4):
      print(list(chunk))

学习链接

猜你喜欢

转载自blog.csdn.net/tyro_java/article/details/80732366