默认情况下记住所有方法 [英] Memoizing all methods by default

查看:68
本文介绍了默认情况下记住所有方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个应用程序,该应用程序可以收集并显示来自科学仪器的数据.数据之一是频谱:本质上只是一个值列表,外加带有一些元数据的字典.一旦应用程序收集了数据,它就不会更改,因此列表和元数据都可以被认为是不可变的.

I’m writing an application that collects and displays the data from a scientific instrument. One of the pieces of data is a spectrum: essentially just a list of values, plus a dictionary with some metadata. Once the data has been collected by the application it does not change, so both the list and the metadata can be considered immutable.

我想通过大量记忆在频谱上执行计算的功能来利用这一优势.这是一个玩具示例:

I’d like to use this to my advantage by heavily memoizing the functions that perform calculations on the spectrum. Here’s a toy example:

class Spectrum(object):
    def __init__(self, values, metadata):
        self.values = values
        self.metadata = metadata
        # self.values and self.metadata should not change after this point.

    @property
    def first_value(self):
        return self.values[0]

    def multiply_by_constant(self, c):
        return [c*x for x in self.values]

    def double(self):
        return self.multiply_by_constant(2)

我想要的是默认情况下会记住这些方法中的每一个.是否有某种方法(元类?)无需复制到这些备注修饰符之一并编写无处不在?

What I want is for each of these methods to be memoized by default. Is there some way (a metaclass?) to accomplish this without copying in one of these memoization decorators and writing @memoize everywhere?

推荐答案

我继续写了一个元类来解决您的问题.它遍历所有属性,并检查它们是否可调用(通常是函数,方法或类),并装饰可调用的属性.当然,您可以将decorator设置为记忆装饰器(例如functools.lru_cache).

I went ahead and wrote a metaclass to solve your question. It loops over all attributes and checks if they are callable (usually a function, method or class) and decorates those which are. Of course you would set decorator to your memoizing decorator (eg. functools.lru_cache).

如果仅 要装饰方法,而不是任何可调用方法,则可以将测试hasattr(val, "__call__")替换为inspect.ismethod(val).但是它可能会在将来引入一个错误,使您不记得它仅适用于方法,并添加一个函数或类,而这些将不会被记住!

If you only want to decorate the methods, and not any callable, you can replace the test hasattr(val, "__call__") with inspect.ismethod(val). But it could introduce a bug in the future where you don't remember it only works for methods, and add a function or class, which won't be memoized!

请参见询问有关Python中元类的更多信息.

See this SO question for more info about metaclasses in Python.

def decorate(f):
    def wrap(*args, **kwargs):
        # Print a greeting every time decorated function is called
        print "Hi from wrap!"
        return f(*args, **kwargs)
    return wrap

class DecorateMeta(type):
    def __new__(cls, name, bases, dct):
        # Find which decorator to use through the decorator attribute
        try:
            decorator = dct["decorator"]
        except KeyError:
            raise TypeError("Must supply a decorator")

        # Loop over all attributes
        for key, val in dct.items():
            # If attribute is callable and is not the decorator being used
            if hasattr(val, "__call__") and val is not decorator:
                dct[key] = decorator(val)

        return type.__new__(cls, name, bases, dct)

class Test:
    __metaclass__ = DecorateMeta
    decorator = decorate

    def seasonal_greeting(self):
        print "Happy new year!"

Test().seasonal_greeting()

# Hi from wrap!
# Happy new year!

这篇关于默认情况下记住所有方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆