当前位置: 首页 > 面试题库 >

python resettable实例方法备忘录装饰器

穆仲卿
2023-03-14
问题内容

我正在尝试为将记住结果的类的实例方法构建装饰器。(这已经完成了一百万次了)但是,我希望可以在任何时候重置已记忆的缓存(例如,如果实例状态中的某些内容发生了更改,这可能会更改没有任何内容的方法的结果)与它的参数有关)。因此,我尝试将装饰器构建为类而不是函数,以便我可以作为类成员访问缓存。这使我走下了学习描述符的道路,特别是__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__,但进展不大。

我是否完全没有针对此问题的完全独立的方法?并欢迎所有建议/建议。谢谢。


问题答案:

我没有尝试弄清实现的机制,而是memoized从PythonDecoratorLibrary获取了decorator类,并将其修改为add
reset。结果如下:我使用的技巧是reset在装饰后的函数本身中添加一个callable属性。

    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)


 类似资料:
  • 问题内容: 考虑这个小例子: 哪个打印 为什么参数(应该是Test obj实例)没有作为第一个参数传递给装饰函数? 如果我手动进行操作,例如: 它按预期工作。但是,如果我必须事先知道某个函数是否装饰,它就破坏了装饰器的全部目的。这里的模式是什么,还是我误会了什么? 问题答案: tl; dr 您可以通过将类作为描述符并返回部分应用的函数来解决此问题,该函数从中应用对象作为参数之一,如下所示 实际问题

  • 本文向大家介绍vue.js实现备忘录功能的方法,包括了vue.js实现备忘录功能的方法的使用技巧和注意事项,需要的朋友参考一下 这个vue实现备忘录的功能demo是K在github上找到的,K觉得这是一个用来对vue.js入门的一个非常简单的demo,所以拿在这里共享一下。 (尊重他人劳动成果,从小事做起~  demo原github地址:https://github.com/vuejs/vue)

  • 本文向大家介绍基于Python 装饰器装饰类中的方法实例,包括了基于Python 装饰器装饰类中的方法实例的使用技巧和注意事项,需要的朋友参考一下 title: Python 装饰器装饰类中的方法 comments: true date: 2017-04-17 20:44:31 tags: ['Python', 'Decorate'] category: ['Python'] --- 目前在中文网

  • 本文向大家介绍JS操作COOKIE实现备忘记录的方法,包括了JS操作COOKIE实现备忘记录的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JS操作COOKIE实现备忘记录的方法。分享给大家供大家参考,具体如下: 具体涉及JS针对cookie的写入与获取操作,代码如下: 更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript查找算法技巧总结》、《Jav

  • 本文向大家介绍C#备忘录模式(Memento Pattern)实例教程,包括了C#备忘录模式(Memento Pattern)实例教程的使用技巧和注意事项,需要的朋友参考一下 本文以一个简单实例讲述了C#备忘录模式(Memento Pattern)的实现方法。分享给大家供大家参考。具体实现方法如下: 简单来说,备忘录模式就是支持回退操作。假设让一个Notepad支持回退操作,如何实现呢? 首先需要

  • 本文向大家介绍Vue.js实现备忘录功能,包括了Vue.js实现备忘录功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Vue.js实现备忘录的具体代码,供大家参考,具体内容如下 效果展示: html代码: CSS代码: js代码:  以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 主要内容:介绍,实现,Memento.java,Originator.java,CareTaker.java,MementoPatternDemo.java备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 介绍 意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 主要解决:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先

  • 备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 介绍 意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 主要解决:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。 何时使用:很多时候我们总是需要记录一个对象