修改可变参数的函数的Python备忘录
假设我有一个修改列表参数和备忘录装饰器的函数,例如:修改可变参数的函数的Python备忘录,python,mutable,memoization,Python,Mutable,Memoization,假设我有一个修改列表参数和备忘录装饰器的函数,例如: @memoizer def add_1_to_list(list): for i in range(len(list)): list[i] += 1 return list 在我的主程序中,我有 list = [1, 1, 1, 1] add_1_to_list(list) print list 如果我的Memorizer类只缓存返回值并将add\u 1\u设置为返回相同的值,那么当我第一次运行主程序时,它
@memoizer
def add_1_to_list(list):
for i in range(len(list)):
list[i] += 1
return list
在我的主程序中,我有
list = [1, 1, 1, 1]
add_1_to_list(list)
print list
如果我的Memorizer类只缓存返回值并将add\u 1\u设置为返回相同的值,那么当我第一次运行主程序时,它将打印[2,2,2,2]
,而第二次,它将打印[1,1,1]
,因为列表是可变的
有没有什么解决方案可以让记忆器类检测函数修改了参数,这样我们就可以记录它并保存修改后的参数?通过在memoizer类中调用前后打印参数,我可以直观地看到它,但在不知道参数是什么类型以及它们是否可变/不可变的情况下,似乎很难测试参数是否已修改。不确定memoizer是如何实现的,但是您可以使用函数参数作为缓存的键。比如:
def memoizer(func):
mem = {}
def wrapped(lst):
key = tuple(lst)
if key not in mem:
print 'Actually computing for input %s...' % lst
mem[key] = []
mem[key][:] = func(lst)
lst[:] = mem[key]
return mem[key]
return wrapped
@memoizer
def add_1_to_list(list):
for i in range(len(list)):
list[i] += 1
return list
# Case 1
lst = [1, 1, 1, 1]
print 'Given', lst
print add_1_to_list(lst)
print add_1_to_list(lst)
print 'Finally lst is:', lst
# Case 2
lst = [1, 1, 1, 1]
print 'Given', lst
print add_1_to_list(lst)
print 'Finally lst is:', lst
请注意,mem[key][:]
将是必需的,因为add_1_to_list
不会在内部创建新列表,因此我们需要复制结果lst[:]=mem[key]
模仿add_1_to_list
的行为,即修改给定的输入列表
案例1的输出:
给定[1,1,1,1]
实际计算输入[1,1,1,1]
[2,2,2,2]
实际计算输入[2,2,2,2]
[3,3,3,3]
最后,lst是:[3,3,3,3]
现在,一些缓存已就绪:
给定[1,1,1,1]
[2,2,2,2]
最后,lst是:[2,2,2,2]
对你的问题唯一可能的答案是不要。您使用的是不应使用备忘录的备忘录 只记忆没有副作用的功能,否则你会自找麻烦 有什么解决方案可以让记忆器类检测函数修改参数吗 检测易变性不是回忆体的责任,而是程序员的责任来决定是否将回忆体应用于函数 这样我们就可以记录它并保存修改过的参数
对我来说,这听起来像是把事情复杂化了。此外,如果“保存”修改后的参数,最终会保留对它们的引用,从而阻止它们被释放。但这假设我们知道参数的类型,即列表,它是可变的。我的问题是想出一个我们不知道它是什么类型的解决方案。我尝试通过查看参数是否可散列来测试易变性,但后来被numpy数组卡住了,它既可以是易变的,也可以是可散列的。也许我应该使用你的方法,但使用一个try块。我实际上是想将它们保存到一个文件中,而不是让它们在程序中运行,但是你说的很有意义。或者副作用是幂等的:)