zl程序教程

您现在的位置是:首页 >  Python

当前栏目

python/测试/测开-刷题第3天

2023-03-20 14:54:03 时间

背景介绍

  • 整理面试题,开始刷题【python】【测试】【测开】相关。

解决方案

  • 人无我有,人有我精

面试题03:说一下你对Python中迭代器和生成器的理解。

点评:很多人面试者都会写迭代器和生成器,但是却无法准确的解释什么是迭代器和生成器。如果你也有同样的困惑,可以参考下面的回答。

  1. 迭代器是实现了迭代器协议的对象。

跟其他编程语言不同,Python中没有用于定义协议或表示约定的关键字,像interface、protocol这些单词并不在Python语言的关键字列表中。

Python语言通过魔法方法来表示约定,也就是我们所说的协议,而__next__和__iter__这两个魔法方法就代表了迭代器协议。

可以通过for-in循环从迭代器对象中取出值,也可以使用next函数取出迭代器对象中的下一个值。

  1. 生成器是迭代器的语法升级版本,可以用更为简单的代码来实现一个迭代器。

什么是迭代器

顾名思义,迭代器就是用于迭代操作(for 循环)的对象,它像列表一样可以迭代获取其中的每一个元素,任何实现了 「next」 方法 (python2 是 next)的对象都可以称为迭代器。

它与列表的区别在于,构建迭代器的时候,不像列表把所有元素一次性加载到内存,而是以一种延迟计算(lazy evaluation)方式返回元素,这正是它的优点。比如列表含有中一千万个整数,需要占超过400M的内存,而迭代器只需要几十个字节的空间。因为它并没有把所有元素装载到内存中,而是等到调用 next 方法时候才返回该元素(按需调用 call by need 的方式,本质上 for 循环就是不断地调用迭代器的next方法)。

迭代器实操【可能会让你手写的】

写生成斐波那契数列的迭代器

  • 迭代器
class Fib(object):

    def __init__(self, num):
        self.num = num
        self.a, self.b = 0, 1
        self.idx = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.idx < self.num:
            self.a, self.b = self.b, self.a + self.b
            self.idx += 1
            return self.a
        raise StopIteration()

什么是生成器

生成器本质上还是一个迭代器

知道迭代器之后,就可以正式进入生成器的话题了。普通函数用 return 返回一个值,和 Java 等其他语言是一样的,然而在 Python 中还有一种函数,用关键字 yield 来返回值,这种函数叫生成器函数,函数被调用时会返回一个生成器对象,「生成器本质上还是一个迭代器」,也是用在迭代操作中,因此它有和迭代器一样的特性,唯一的区别在于实现方式上不一样,后者更加简洁。

生成器实操【可能会让你手写的】

用生成器的语法来改写上面的代码,代码会简单优雅很多。

def fib(num):
    a, b = 0, 1
    for _ in range(num):
        a, b = b, a + b
        yield a