2014-02-07 31 views
1

說我有修改列表參數和memoizer裝飾功能的功能,如:的Python memoization的那些修改可變參數

@memoizer 
def add_1_to_list(list): 
    for i in range(len(list)): 
     list[i] += 1 
    return list 

在我的主程序,我有

list = [1, 1, 1, 1] 
add_1_to_list(list) 
print list 

如果我的memoizer類只緩存返回值並將add_1_to_list設置爲返回相同的值,那麼當我第一次運行主程序時,它將打印[2, 2, 2, 2],而第二次它將打印[1, 1, 1, 1],因爲列表是可變的。

是否有任何解決方案可以讓memoizer類檢測到函數修改了一個參數,這樣我們可以記下它並保存修改的參數?通過在memoizer類中調用它之前和之後打印參數,我可以直觀地看到它,但不知道參數是什麼類型以及它們是否可變/不可變,似乎很難測試參數是否已被修改。

回答

1

唯一可能的答案,你的追求離子是不要。您正在使用memoization不應使用memoization。

只記憶沒有任何副作用的功能,或者你在尋求麻煩。

是否有任何解決方案來獲取memoizer類來檢測該函數修改參數?

檢測可變性不是檢測器的責任,程序員有責任決定是否將備忘錄應用到函數中。

這樣,我們可以注意到它並保存修改的參數

這聽起來好像過於複雜的事情。此外,如果您「保存」修改後的參數,則最終會保留對它們的引用,從而防止它們被釋放。

+0

我實際上會將它們保存到一個文件中,而不是讓它們繼續保存在程序中,但是您所說的內容很有意義。 – mlstudent

0

不知道如何實現memoizer,但可以使用函數參數作爲緩存內存的關鍵字。喜歡的東西:

def memoizer(func): 

    mem = {} 

    def wrapped(lst): 
     key = tuple(lst) 
     if key not in mem: 
      print 'Actually computing for input %s...' % lst 
      mem[key] = [] 
      mem[key][:] = func(lst) 
     lst[:] = mem[key] 
     return mem[key] 

    return wrapped 

@memoizer 
def add_1_to_list(list): 
    for i in range(len(list)): 
     list[i] += 1 
    return list 

# Case 1 
lst = [1, 1, 1, 1] 
print 'Given', lst 
print add_1_to_list(lst) 
print add_1_to_list(lst) 
print 'Finally lst is:', lst 

# Case 2 
lst = [1, 1, 1, 1] 
print 'Given', lst 
print add_1_to_list(lst) 
print 'Finally lst is:', lst 

注意mem[key][:]將是必要的,因爲add_1_to_list不會在內部創建一個新的列表,所以我們需要的結果的副本。 lst[:] = mem[key]模仿修改給定輸入列表的add_1_to_list的行爲。案例1的

輸出:

鑑於[1,1,1,1]

實際上計算用於輸入[1,1,1,1] ...

[ 2,2,2,2]

實際上計算用於輸入[2,2,2,2] ...

[3,3,3,3]

最後LST爲:[3,3,3,3]

一些高速緩存準備

目前:

鑑於[1,1,1,1]

[2 ,2,2,2]

最後地表溫度:2,2,2,2]

+0

但是,這假定我們知道什麼類型的參數,即一個可變的列表。我的問題是想出一個解決方案,我們不知道它是什麼類型。我試着通過查看參數是否可散列來測試可變性,但是後來遇到了numpy數組,這些數組都是可變的且可散列的。也許我應該使用你的方法,但使用try塊。 – mlstudent