如何使Python记住在函数内创建的列表以供将来使用

时间:2017-09-28 08:58:28

标签: python scope fibonacci memoization

下面是Fibonacci Sequence的迭代计算。

def fibonacci(n):
    if n < 0:
            raise ValueError("invalid index!")
    if n==0:
            return 0
    if n==1:
            return 1

    f = [0,1]
    for i in range(2,n+1):
            f.append(f[i-1] + f[i-2])
    return f[n]

Code Source: brilliant.org

实际上,列表f是函数内部的局部变量,每次调用fibonacci函数时都会重新创建并重新填充。 如何重写此代码段,以便Python在调用后不需要重新计算fibonacci(5),并且可以在下次调用fibonacci(5)或更高版本时使用它?我知道全局变量是一个选项,但这样做最“Pythonic”的方式是什么?

4 个答案:

答案 0 :(得分:3)

您可以将f存储在函数范围 变量中。例如:

def memoize_fibonacci():
    f = [0,1]
    def inner_fibonacci(n):
        if n < 0:
                raise ValueError("invalid index!")
        for i in range(len(f),n+1):
                f.append(f[i-1] + f[i-2])
        return f[n]
    return inner_fibonacci

所以每次我们检查f的长度。如果我们还没有生成请求的索引,我们生成直到获得索引。无论我们是否扩展列表,我们最终都可以返回f[n]

现在我们可以使用:

提取fibonacci函数
fibonacci = memoize_fibonacci()

如果我们现在为200'000th元素查询两次,第二次更快。

答案 1 :(得分:1)

您可以使用闭包来记忆结果:在这种情况下,会在首次执行该函数时创建备忘录dict(通常是在加载模块时);它是持久的,并在调用函数时填充。

def fibonacci(n, memo={}):
    try: 
        return memo[n]
    except KeyError:
        pass
    if n < 0:
            raise ValueError("fibonacci must be called with positive numbers")
    if n == 0:
        memo[n] = 0 
        return 0
    if n == 1:
        memo[n] = 1
        return 1
    memo[n] = fibonacci(n-1) + fibonacci(n-2)
    return memo[n]

答案 2 :(得分:1)

如果您使用的是Python 3.2+,请使用<v11:SquareName xmlns:v11="http://example.com">ABCD</v11:SquareName> https://docs.python.org/3/library/functools.html#functools.lru_cache

答案 3 :(得分:-1)

使用python字典并检查密钥是否存在并从字典中返回结果或计算并在返回之前将结果添加到字典中。

fib_dict = {};

def fibonacci(n):
    if n in fib_dict:
        return fib_dict[n];
    else:
        if n < 0:
            raise ValueError("invalid index!")
        if n==0:
            return 0
        if n==1:
            return 1

        f = [0,1]
        for i in range(2,n+1):
            f.append(f[i-1] + f[i-2])

        fib_dict[n] = f[n];
        return f[n];