python用类写一个装饰器

时间:2012-11-08 15:35:59

标签: python decorator mutable

这是我写一个帮手装饰模块的努力:

# -*- 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'

列表,字典或其他来自集合的可变输入会调用此类错误。 我尝试了所有的args,但显然这没有帮助。我应该如何重写我的代码,以便我的装饰器可以使用任何(好吧,只是字典,列表,元组,集合,整数​​,字符串......可以)输入?

2 个答案:

答案 0 :(得分:1)

我建议在散列之前序列化可变参数,例如使用pickle模块。函数参数中任何dict,list或类似的内容都必须是可选择的,否则将引发PicklingError。在memoizedf的定义中,您可以使用以下代码:

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

很多对象都是可选择的,但不是可以删除的,所以这应该扩展你可以处理的参数类。

答案 1 :(得分:-1)

这样可以解决问题:

key = str(tuple(args))