3

here is my effort in writing a helper decorator module:

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

so, usage:

@timer
def foo():
    print 'foo'

'foo'
00023.1231203879 ms


@memo
def bar(fooobject):
    print fooobject

the problem comes here:

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

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

every input of list, dict, or other mutable from collections would invoke such error. I tried tupling all args, but apparently this didn't help. How should I rewrite my code in order to have my decorator to work with any(well, just dict, list, tuple, set, int, string... would be ok) kind of input?

thkang
  • 11,215
  • 14
  • 67
  • 83

2 Answers2

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.

silvado
  • 17,202
  • 2
  • 30
  • 46
-1

This will do the trick:

key = str(tuple(args))
RickyA
  • 15,465
  • 5
  • 71
  • 95
  • The `str()` function is generally not guaranteed to return a useful result for memoizing objects. – silvado Nov 08 '12 at 16:23