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'

list、dict 或集合中其他可变的每个输入都会引发此类错误。我尝试对所有参数进行元组处理,但显然这没有帮助。我应该如何重写我的代码才能让我的装饰器与任何类型的输入一起工作(好吧,只是 dict、list、tuple、set、int、string... 可以)?

4

2 回答 2

1

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

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

许多对象是可腌制的,但不是可散列的,因此这应该扩展您可以显着处理的参数类。

于 2012-11-08T16:19:58.107 回答
-1

这可以解决问题:

key = str(tuple(args))
于 2012-11-08T16:20:28.047 回答