导入函数的记忆
Posted
技术标签:
【中文标题】导入函数的记忆【英文标题】:Memoization of Imported Functions 【发布时间】:2020-11-07 18:34:26 【问题描述】:我正在创建一个装饰器来说明记忆。对于大多数人来说,我使用的是递归定义的斐波那契函数。
我了解,将函数的记忆版本命名为与原始版本不同会导致效率低下,因为递归调用将激活未记忆的函数。 (见这个老问题,Memoization python function)
我的问题是我似乎找不到正确的语法来覆盖导入函数的名称。
from fibonacci import fibonacci
def with_memoization(function):
past_results =
def function_with_memoization(*args):
if args not in past_results:
past_results[args] = function(*args)
return past_results[args]
return function_with_memoization
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
fib = with_memoization(fib)
fibonacci = with_memoization(fibonacci)
print(fib(100)) # completes in <1 second
print(fibonacci(100)) # completes in >2 minutes, probably hours
这里导入的fibonacci函数和fib函数是一样的。我错过了什么?
【问题讨论】:
问题是导入的函数是在模块的命名空间中查找它的名字,而不是你重新定义函数的命名空间。from fibonacci import fibonacci
之后,你没有名字,你可以在下面存储装饰函数,fibonacci
会递归地找到它。改用import fibonacci
,并使用fibonacci.fibonacci
申请并调用装饰器。
@jasonharper 大声笑,我自己就知道了。谢谢,快写出来,我会接受的..
@jasonharper 但这行得通吗?导入的函数将通过创建函数时已绑定的模块中的本地对象引用自身。
@MarkRansom 它确实有效。
【参考方案1】:
from module import function
语句将模块中的函数别名为function
。因此,当它被修饰时,只有别名被修饰。递归调用是对非别名函数(在模块中),即未修饰的函数。
您可以将其视为创建部分内存,别名函数将记住它自己的计算结果,但不会记住中间步骤。在上面的代码中,fibonacci(100)
将是完成后字典中的唯一条目。 (别等了。)
使用import module
语法不会给函数起别名,module.function
是它的“真实”名称。因此,应用于fibonacci.fibonacci
的修饰也会修饰被递归调用的函数。
工作实施:
import fibonacci
def with_memoization(function):
past_results =
def function_with_memoization(*args, **kwargs):
if args not in past_results:
past_results[args] = function(*args, **kwargs)
return past_results[args]
return function_with_memoization
fibonacci.fibonacci = with_memoization(fibonacci.fibonacci)
print(fibonacci.fibonacci(100))
【讨论】:
以上是关于导入函数的记忆的主要内容,如果未能解决你的问题,请参考以下文章