2012-04-14 63 views
1

有一個在http://pythonprogramming.jottit.com/functional_programming一個教程,它給出了一個例子,如何使用高階函數返回功能:是否有可能從兩個高階函數指定返回值Python中相同的變量[查看詳細]

def trace(f): 
    f.indent = 0 
    def g(x): 
     print '| ' * f.indent + '|--', f.__name__, x 
     f.indent += 1 
     value = f(x) 
     print '| ' * f.indent + '|--', 'return', repr(value) 
     f.indent -= 1 
     return value 
    return g 

def memoize(f): 
    cache = {} 
    def g(x): 
     if x not in cache: 
      cache[x] = f(x) 
     return cache[x] 
    return g 

,但我不明白它是如何能夠在報表上的同一個變量分配兩個功能:

fib = trace(fib) 
fib = memoize(fib) 
print fib(4) 

跟蹤和記憶似乎對最後一次呼叫有影響。這是爲什麼?

+1

「既跟蹤和memoize的似乎對最後的通話效果」他們都被叫了。還有其他問題嗎? – 2012-04-14 04:09:53

回答

2

兩個trace()memoize()創建一個新的函數對象,並將其返還給您。

在每種情況下,新的函數對象「包裝」老函數對象,所以原來的功能不會丟失。

用我驚人的ASCII藝術技能,這裏是一個圖:

f(x) # this is your original function 

trace(f(x)) # trace "wraps" it and returns a wrapped object 

memoize(trace(f(x))) # memoize "wraps" it and returns a new wrapped function object 

我們開始了與綁定到名稱fib一個函數對象。

則稱trace(fib)這將創建一個新的函數對象。當它第一次創建時,其名稱是g,但我們將它綁定到名稱fib。嘗試打印fib.__name__

則稱memoize(fib)這將創建一個新的函數對象。它再次以名稱g創建,但隨後綁定到名稱fib

記住,Python中一切都是對象,並且對象可以沒有名字的存在,有一個名字,或者有許多名字。在這種情況下,我們繼續使用名稱fib,但我們不斷使用不同的函數對象重新綁定它。

2

這是沒有什麼不同:

a = a + 2 
a = a + 5 
print a 

正如a將增加7,fib將有兩個裝飾應用了。

+0

對不起@Ignacio上面的比喻感覺不同於我的問題。在你的情況下,a被一個新值「覆蓋」我沒有更多的東西。也許我必須閱讀裝飾器。我認爲這兩個函數都會生成新的函數,而fib將在第二個任務上被覆蓋。你能告訴我幕後發生了什麼嗎? – 2012-04-14 10:50:12

+0

'fib'被覆蓋。他們對fib *用來包含的對象的引用僅僅是絨毛。 – 2012-04-14 14:00:09

+0

它如何執行這兩項工作(追蹤,記憶)呢? – 2012-04-14 18:47:57

3

你寫的是非常相似的

fib2 = memoize(trace(fib)) 
print fib2(4) 

,因爲你已經改變了功能變量fib指向調用trace後,所以memoize應用於跟蹤版本(然後fib是「重寫」)。

如果要單獨有一個跟蹤版本和memoized版本,你需要分配的結果不同的變量,如:

fib_trace = trace(fib) 
fib_memo = memoize(fib) 
print fib_trace(4), fib_memo(4) 
相關問題