如何让 Python 记住在函数内部创建的列表以备将来使用
How to Make Python remember a list created inside a function for future use
下面是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]
实际上,列表 f
是函数内部的局部变量,每次调用 fibonacci
函数时都会重新创建和重新填充。
如何重写此代码片段,以便 Python 在调用后不需要重新计算 fibonacci(5)
并且可以在下次调用 fibonacci(5)
或更高版本时使用它?我知道全局变量是一种选择,但最 "Pythonic" 的方法是什么?
您可以使用闭包来记忆结果:在这种情况下,备忘录字典是在函数首次执行时创建的(通常是在加载模块时);它是持久的,并在调用函数时填充。
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]
您可以将 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
的长度。如果我们还没有生成请求的索引,我们会生成直到我们获得索引。不管我们是否扩展列表,我们最终都可以 return f[n]
.
现在我们可以提取 fibonacci
函数,其中:
fibonacci = memoize_fibonacci()
如果我们现在为第 200'000 个元素查询两次,第二次会更快。
使用 python 字典并检查密钥是否存在以及 return 来自字典的结果,或者在 returning 之前计算并将结果添加到字典中。
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];
下面是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]
实际上,列表 f
是函数内部的局部变量,每次调用 fibonacci
函数时都会重新创建和重新填充。
如何重写此代码片段,以便 Python 在调用后不需要重新计算 fibonacci(5)
并且可以在下次调用 fibonacci(5)
或更高版本时使用它?我知道全局变量是一种选择,但最 "Pythonic" 的方法是什么?
您可以使用闭包来记忆结果:在这种情况下,备忘录字典是在函数首次执行时创建的(通常是在加载模块时);它是持久的,并在调用函数时填充。
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]
您可以将 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
的长度。如果我们还没有生成请求的索引,我们会生成直到我们获得索引。不管我们是否扩展列表,我们最终都可以 return f[n]
.
现在我们可以提取 fibonacci
函数,其中:
fibonacci = memoize_fibonacci()
如果我们现在为第 200'000 个元素查询两次,第二次会更快。
使用 python 字典并检查密钥是否存在以及 return 来自字典的结果,或者在 returning 之前计算并将结果添加到字典中。
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];