为什么这个python函数中的一行是必要的?(记忆化递归)

12 投票
1 回答
588 浏览
提问于 2025-04-17 08:32

我从Peter Norvig的网站上找到了以下代码片段;这是一个装饰器,用来给函数调用加上记忆化(也就是缓存之前的函数调用结果,这样可以把复杂的递归变成简单的动态规划)。

def memo(f):
    table = {}
    def fmemo(*args):
        if args not in table:
            table[args] = f(*args)
        return table[args]
    fmemo.memo = table
    return fmemo

这段代码运行得很好,但我在想为什么倒数第二行是必要的。显然这是我对Python知识的一个盲点,但我把那行去掉后,运行一个简单的斐波那契函数,似乎还是能正常工作。这是不是和同时记忆化多个函数有关?为什么fmemo的成员变量叫做memo(假设这不是个巧合)?

谢谢!

1 个回答

12

因为函数和其他任何东西一样,都是对象,所以你可以给它们设置属性。看看这个:

>>> def foo(): pass
>>> foo.x = 1
>>> foo.x
1

第二行代码把一个内部的值缓存设置为函数对象的一个属性,这样就可以直接访问它了。这意味着你可以对一个已经记忆化的函数的缓存进行修改,而不需要去调用这个函数。这可能会很方便。


举个例子:

>>> @memo
... def id(x): return x
>>> id(1)
1
>>> id(2)
2
>>> id.memo
{(2,): 2, (1,): 1}

撰写回答