2012-11-08 147 views
3

這裏是我努力寫一個輔助裝飾模塊:蟒蛇寫一個裝飾用

# -*- coding: utf8 -*- 

import time 
def timer(func): 
    def timed(*args, **kwargs): 
     init = time.clock() 
     result = func(*args, **kwargs) 
     print (time.clock()-init)*1000, 'ms' 

     return result  
    return timed 

class memo(object): 
    def __init__(self, func): 
     self.func = func 
     self.memo = {} 
     self.memohit = 0 

    def memoizedf(self, *args): 
     key = tuple(args) 
     print key 
     lookup = self.memo.setdefault(key, None) 
     if lookup: 
      self.memohit += 1 
      return lookup 

     result = self.func(*args) 
     self.memo[key]=result 
     return result 

    def __call__(self, *args): 
     return self.memoizedf(*args) 

所以,用法:

@timer 
def foo(): 
    print 'foo' 

'foo' 
00023.1231203879 ms 


@memo 
def bar(fooobject): 
    print fooobject 

問題就來了這裏:

>>bar({'foo':'bar'}) 

traceback : ........... 
    lookup = self.memo.setdefault(key, None) 
TypeError: unhashable type: 'dict' 

列表,字典或其他集合中的每個輸入都會引發這樣的錯誤。 我試圖把所有的參數都打亂,但顯然這沒有幫助。我應該如何重寫我的代碼,以使我的裝飾器能夠與任何輸入一起工作(好吧,只是字典,列表,元組,集合,字符串......沒關係)?

+0

有互聯網上的許多memoize的食譜和Python 3.2+帶有'functools.lru_cache' – JBernardo

+1

見http://stackoverflow.com/questions/4669391/python -any-one-memoizing-decorator-that-c​​an-handle-unhashable-arguments – NPE

+0

你只是不能在字典中使用可變對象作爲鍵。也許你可以使用'str'來獲得對象的可散列表示。 –

回答

1

我建議序列化散列前的可變參數,例如使用pickle模塊。函數參數中的任何字典,列表或類似內容必須是可選的,否則將引發PicklingError。在你的memoizedf定義,你可以使用此代碼:

key = pickle.dumps((args,kwargs)) 
lookup = self.memo.setdefault(key, None) 

很多對象都是picklable,但不是哈希的,所以這應該擴展類的,你可以處理顯著參數。

-1

這將這樣的伎倆:

key = str(tuple(args)) 
+0

'str()'函數通常不能保證爲記憶對象返回有用的結果。 – silvado