假设我有一个修改list参数和memoizer装饰器的函数,例如:
@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
如果我的memoizer类只缓存返回值并设置add_1_to_list以返回相同的值,那么当我第一次运行主程序时,它将打印[2, 2, 2, 2]
,而第二次,它将打印{ {1}},因为列表是可变的。
是否有任何解决方案可以让memoizer类检测到函数修改了一个参数,这样我们就能记下它并保存修改过的参数?通过在memoizer类中调用它之前和之后打印参数,我能够直观地看到它,但是在不知道参数是什么类型以及它们是否是可变/不可变的情况下,似乎很难测试参数是否已被修改
答案 0 :(得分:1)
您的问题唯一可能的答案是不要。你正在使用memoization,不应该使用memoization。
只记忆没有副作用的功能,或者你要求麻烦。
是否有任何解决方案可以让memoizer类检测函数是否修改了参数?
记忆者没有责任检测可变性,程序员有责任决定是否将记事本应用于该功能。
这样我们可以记下它并保存修改过的参数
这听起来像是过于复杂的事情。此外,如果你“保存”修改过的参数,你最终会保留对它们的引用,防止它们被释放。
答案 1 :(得分:0)
不确定如何实现memoizer,但可以使用function参数作为缓存内存的关键字。类似的东西:
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]
最后,我是:[3,3,3,3]
现在准备好一些缓存:
给出[1,1,1,1]
[2,2,2,2]
最后,我是:[2,2,2,2]