python resettable实例方法memoization装饰器

Hoo*_*pes 10 python decorator memoization descriptor

我正在尝试为类的实例方法构建一个装饰器来记忆结果.(之前已经完成了一百万次)但是,我希望能够在任何时候重置memoized缓存(例如,如果实例状态中的某些内容发生更改,这可能会更改无方法的结果)与它的args相关).所以,我试图建立一个装饰为一类,而不是一个函数,这样我可以有机会获得高速缓存作为一个类的成员.这导致我学习描述符的路径,特别是__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)
Run Code Online (Sandbox Code Playgroud)

这是清楚的和/或可能的吗?每次__get__被调用时,我得到的memoized类,它失去了我的缓存,它的实际数据的一个全新的实例.我一直在努力__get__,但没有取得多大进展.

是否有一个完全独立的方法解决这个问题,我完全不知道了?并且欢迎并赞赏所有建议/建议.谢谢.

NPE*_*NPE 7

我没有尝试计算实现的机制,而是memoizedPythonDecoratorLibrary中获取了装饰器类,并修改了它以进行添加reset.以下是结果; 我使用的技巧是为reset装饰函数本身添加一个可调用属性.

    class memoized2(object):
       """Decorator that caches a function's return value each time it is called.
       If called later with the same arguments, the cached value is returned, and
       not re-evaluated.
       """
       def __init__(self, func):
          self.func = func
          self.cache = {}
       def __call__(self, *args):
          try:
             return self.cache[args]
          except KeyError:
             value = self.func(*args)
             self.cache[args] = value
             return value
          except TypeError:
             # uncachable -- for instance, passing a list as an argument.
             # Better to not cache than to blow up entirely.
             return self.func(*args)
       def __repr__(self):
          """Return the function's docstring."""
          return self.func.__doc__
       def __get__(self, obj, objtype):
          """Support instance methods."""
          fn = functools.partial(self.__call__, obj)
          fn.reset = self._reset
          return fn
       def _reset(self):
          self.cache = {}


    class my_class:
        @memoized2
        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)
Run Code Online (Sandbox Code Playgroud)