2015-12-02 59 views
1

我有下面的代碼python裝飾器如何與遞歸一起工作?

def memo(fn): 
    cache = {} 
    miss = object() 
    print 'MEMO' 
    def wrapper(*args): 
     result = cache.get(args, miss) 
     print 'IT CALLS' 
     if result is miss: 
      print 'IT MISSES' 
      result = fn(*args) 
      cache[args] = result 
     return result 
    return wrapper 

@memo 
def fib(n): 
    if n < 2: 
     return n 
    return fib(n - 1) + fib(n - 2) 

當我打電話FIB(4)它打印MEMO只有一次。以下是輸出。

MEMO 
IT CALLS 
IT MISSES 
IT CALLS 
IT MISSES 
IT CALLS 
IT MISSES 
IT CALLS 
IT MISSES 
IT CALLS 
IT MISSES 
IT CALLS 
IT CALLS 

是什麼導致了這種行爲?

+0

可能是非相關的,但您可能想要使用(fib(n),fib(n-1))的元組作爲fib函數的返回值來使用fib的線性計算。 – DainDwarf

+0

你真的想閱讀[this excellent answer]的所有*(https://stackoverflow.com/a/1594484/100297)。 –

回答

3

這是正確的行爲,與遞歸無關。

當裝飾器被調用時會打印MEMO,當它被應用於函數時會發生;即在定義時間。如果你從來沒有打電話給fib(),MEMO仍然會被打印。

2

你只打印MEMO申請裝飾。它不是wrapper函數的一部分,這是裝飾器生成的用於替換原始函數的部分。