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'

リスト、dict、またはコレクションからのその他の変更可能なすべての入力は、このようなエラーを引き起こします。すべての引数をタプルしようとしましたが、明らかにこれは役に立ちませんでした。デコレータがあらゆる種類の入力 (まあ、dict、list、tuple、set、int、string ... だけでOK) で動作するようにするには、コードをどのように書き直せばよいでしょうか?

4

2 に答える 2

1

I'd suggest to serialize the mutable arguments before hashing, for example using the pickle module. The contents of any dict, list, or similar in the function arguments have to be picklable, otherwise a PicklingError will be raised. In your definition of memoizedf, you could use this code:

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

A lot of objects are picklable, but not hashable, so this should extend the class of arguments that you can deal with significantly.

于 2012-11-08T16:19:58.107 に答える
-1

This will do the trick:

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