修改可变参数的函数的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块。我实际上是想将它们保存到一个文件中,而不是让它们在程序中运行,但是你说的很有意义。或者副作用是幂等的:)