【问题标题】:Why is a line in this python function necessary? (memoized recursion)为什么这个 python 函数中需要一行? (记忆递归)
【发布时间】:2012-01-22 10:44:12
【问题描述】:

我从 Peter Norvig 的网站获得了以下代码 sn-p;它是一个装饰器,可以在函数调用上启用记忆(缓存对函数的先前调用以将指数递归更改为简单的动态程序)。

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(假设这不是一个尴尬的巧合)?

谢谢!

【问题讨论】:

  • 您的代码缩进看起来不正确。这是一个嵌套函数吗?
  • 顺便说一句,这已在 Python 3.2 中实现为 functools.lru_cache
  • @MAK:这是一个嵌套函数。这是装饰器的声明
  • @Bean:在我发表评论后,缩进已修复。 NVM。
  • 我的错!一定是错误的复制/粘贴。

标签: python recursion decorator


【解决方案1】:

由于函数和其他任何东西一样都是对象,因此您可以在它们上设置属性。见:

>>> 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}

【讨论】:

  • 我要补充一点,由于关闭,它不是必要的。正如您所说,能够干预或访问值而不需要调用它将是重要的事情。
  • 确实,封闭的table 变量也命名了缓存(如果memo 在外部重新分配,这实际上是有问题的)...但是+1。
  • 确实,重新分配memo 会很糟糕。
  • @Bean: 正确;通常,您无法查看其他人的范围。这就是作用域的用途!
  • @Bean: 你可以看看函数的func_closure tuple。
猜你喜欢
  • 2014-01-21
  • 2022-01-17
  • 2021-10-23
  • 2012-11-26
  • 1970-01-01
  • 2018-07-13
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
相关资源
最近更新 更多