延迟计算在python中的应用

136 阅读2分钟

  最近在学习python,在github上找到一个python的初学者教程,叫做“100_page_python_intro”,跟着看了一遍。

  在看到第18节“Comprehensions and Generator expressions”的时候,发现了一个有意思的东西,叫做generator对象。generator实际是一个iterator(迭代器),但是在迭代器的基础上,它还提供了延迟计算的特性。

  下面我们来看看如何使用generator,我们通过python的yield关键字构造一个可以生成长度为n的斐波那契数列的generator为例子:

# coding=utf-8
def fibonacci(n):
    current, next_ = 0, 1
    for _ in range(n):
        print('before yield~')
        yield current
        print('after yield~')
        current, next_ = next_, current + next_
        print('after calculate~')


generator = fibonacci(10)

print(next(generator))
print(next(generator))
print(next(generator))
print(next(generator))
print(next(generator))

  打下断点,并执行上述代码,在执行完第12行的代码之后,fibonacci函数创建出了一个generator对象,此时,控制台中没有任何输出,说明上述代码中第4、6、8三行都还没执行,而且查看创建出来的generator对象,gi_frame属性中保存了generator执行fibonacci方法的调用栈,顶层的栈帧记录了generator正执行到test.py文件的第二行,还没有去计算斐波那契数列的第三个值。

image-20210405202219489 按下F8,debug过代码第14行,可以看到generator执行到test.py的第6行,返回了斐波那契数列中的第一个数字

image-20210405202733180

image-20210405202837005

  继续按下F8,debug过代码第15行,根据控制台的输出,可以很明显的看到,generator对象,按顺序执行了fibonacci方法中的第7,8,9,5,6行代码,在执行第8行代码的时候,才真正计算出斐波那契数列第3个数字的值。

image-20210405202953689

  延迟计算在代码实现中是十分常见的,之前在学习GUAVA的RateLimiter限流器的时候,RateLimiter也使用了延迟计算的方式,详见我的这篇笔记:GUAVA RateLimiter限流器