2011-12-17 80 views
12

我從Peter Norvig的網站獲得了以下代碼片段;它是一個裝飾器,用於啓用函數調用的memoization(緩存之前調用該函數以將指數遞歸轉換爲簡單的動態程序)。爲什麼在這個python函數中有一行是必需的? (memoized遞歸)

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的成員變量被稱爲備忘錄(假設它不是一個尷尬的巧合)?

謝謝!

+0

代碼的縮進看起來不正確的。這是一個嵌套函數嗎? – MAK 2011-12-17 02:15:49

+0

FTFY ........... – katrielalex 2011-12-17 02:17:55

回答

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}