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

如何让Python记住在函数中创建的列表以供将来使用,python,scope,fibonacci,memoization,Python,Scope,Fibonacci,Memoization,下面是一个迭代计算 def fibonacci(n): 如果n

下面是一个迭代计算

def fibonacci(n):
如果n<0:
raise VALUERROR(“无效索引!”)
如果n==0:
返回0
如果n==1:
返回1
f=[0,1]
对于范围(2,n+1)内的i:
f、 附加(f[i-1]+f[i-2])
返回f[n]

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

您可以使用闭包来记忆结果:在这种情况下,在首次执行函数时(通常是在加载模块时)创建memo 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]
def fibonacci(n,memo={}):
尝试:
返回备忘录[n]
除KeyError外:
通过
如果n<0:
raise VALUERROR(“必须用正数调用斐波那契”)
如果n==0:
备注[n]=0
返回0
如果n==1:
备忘录[n]=1
返回1
备忘录[n]=斐波那契(n-1)+斐波那契(n-2)
返回备忘录[n]

您可以将
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

如果我们现在两次查询第20万个元素,第二次查询速度更快。

使用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];
fib_dict={};
def fibonacci(n):
如果fib_dict中的n:
返回fib_dict[n];
其他:
如果n<0:
raise VALUERROR(“无效索引!”)
如果n==0:
返回0
如果n==1:
返回1
f=[0,1]
对于范围(2,n+1)内的i:
f、 附加(f[i-1]+f[i-2])
fib_dict[n]=f[n];
返回f[n];

global
或将可变变量传递给函数。您可能希望检查更好的实现的备选方案:您应该查找Memorization。举个例子:这有关系吗?我不明白这整件
pythonic
宗教的废话。如果它解决了您的问题,并且是一个可读的或快速的操作,那不是很好吗?无论如何,是的,它是pythonic-.-@Torxed全局变量既不是快速的、线程安全的,也不是pythonic的(这仅仅意味着以最直接和前瞻性的方式使用该语言,而不是像您习惯于使用另一种语言那样)。有很多人喜欢将代码黑客化,而不考虑可维护性或可靠性,所以无论如何都可以随意这么做;-)memo dict是在执行函数定义时创建的(通常是在导入它所驻留的文件时),而不是在第一次调用函数时创建的。由于其递归性质,这会导致初始调用
fibonacci(1000)
,其他解决方案可以处理该调用。备忘录对此没有帮助。另外,从技术上来说,这是一个终结吗?即,谁的变量是
memo
?(除了增加Python的堆栈大小外,您还可以通过调用
fibonacci(900)
before
fibonacci(1000)
来轻松解答这个问题!)这实际上比使用Binet公式要快,也有相当大的差距(!)谢谢,@Willem Van Onsem,如果没有最后一行
fibonacci=memoize\u fibonacci
而只是使用
memoize\u fibonacci
作为函数,会有什么不同吗?就运行时间而言?@Semihcan:是的。因为
memoize\u fibonacci
不是fibonacci函数。它是斐波那契函数的工厂。
fibonacci = memoize_fibonacci()
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];