Декоратор мемоизации метода экземпляра восстанавливаемого экземпляра Python

Я пытаюсь создать декоратор для метода экземпляра класса, который запомнит результат. (Это делалось миллион раз раньше) Однако я бы хотел иметь возможность сбросить мемоизированный кеш в любой момент (скажем, если что-то в состоянии экземпляра изменится, что может изменить результат метода, не имеющего ничего делать с его аргументами). Итак, я попытался создать декоратор как класс, а не функцию, чтобы иметь доступ к кешу как член класса. Это привело меня к изучению дескрипторов, в частности метода __ get __ , в котором я фактически застрял. Мой код выглядит так:

import time

class memoized(object):

    def __init__(self, func):
        self.func = func
        self.cache = {}

    def __call__(self, *args, **kwargs):

        key = (self.func, args, frozenset(kwargs.iteritems()))

        try:
            return self.cache[key]
        except KeyError:
            self.cache[key] = self.func(*args, **kwargs)
            return self.cache[key]
        except TypeError:
            # uncacheable, so just return calculated value without caching
            return self.func(*args, **kwargs)

    # self == instance of memoized
    # obj == instance of my_class
    # objtype == class object of __main__.my_class
    def __get__(self, obj, objtype=None):
        """Support instance methods"""
        if obj is None:
            return self

        # new_func is the bound method my_func of my_class instance
        new_func = self.func.__get__(obj, objtype)

        # instantiates a brand new class...this is not helping us, because it's a 
        # new class each time, which starts with a fresh cache
        return self.__class__(new_func)

    # new method that will allow me to reset the memoized cache
    def reset(self):
        print "IN RESET"
        self.cache = {}

class my_class:
    @memoized
    def my_func(self, val):
        print "in my_func"
        time.sleep(2)
        return val


c = my_class()

print "should take time"
print c.my_func(55)
print

print "should be instant"
print c.my_func(55)
print

c.my_func.reset()

print "should take time"
print c.my_func(55)

Это понятно и / или возможно? Каждый раз, когда вызывается __ get __ , я получаю новый экземпляр мемоизированного класса, который теряет кеш с фактическими данными в нем. Я много работал с __ get __ , но не добился большого прогресса.

Есть ли совершенно отдельный подход к этой проблеме, который мне полностью не хватает? И все советы / предложения приветствуются и ценятся. Спасибо.

10
задан martineau 20 September 2012 в 15:41
поделиться