Python 默认情况下记录所有方法

Python 默认情况下记录所有方法,python,immutability,Python,Immutability,我正在编写一个应用程序,收集和显示科学仪器的数据。其中一部分数据是一个谱:本质上只是一个值列表,加上一个包含一些元数据的字典。一旦应用程序收集了数据,它就不会更改,因此可以认为列表和元数据都是不可变的 我想利用这一点,通过大量记忆在光谱上执行计算的函数来发挥我的优势。下面是一个玩具示例: class Spectrum(object): def __init__(self, values, metadata): self.values = values se

我正在编写一个应用程序,收集和显示科学仪器的数据。其中一部分数据是一个谱:本质上只是一个值列表,加上一个包含一些元数据的字典。一旦应用程序收集了数据,它就不会更改,因此可以认为列表和元数据都是不可变的

我想利用这一点,通过大量记忆在光谱上执行计算的函数来发挥我的优势。下面是一个玩具示例:

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)

我希望这些方法中的每一个都在默认情况下被记忆。有没有什么方法(元类?)可以做到这一点而不必到处抄写
@memoize

我写了一个元类来解决你的问题。它在所有属性上循环,检查它们是否可调用(通常是函数、方法或类),并装饰那些可调用的属性。当然,您会将
decorator
设置为memonizing decorator(例如
functools.lru\u cache

如果您只想修饰方法,而不想调用任何方法,那么可以将test
hasattr(val,“\u call”
替换为
inspect.ismethod(val)
。但它可能会在将来引入一个bug,你不记得它只对方法有效,并添加一个不会被记忆的函数或类

有关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!

我将fridge的答案改编为:

from inspect import isfunction

class Immutable(type):
    def __new__(cls, name, bases, dct):
        for key, val in dct.items():
            # Look only at methods/functions; ignore those with
            # "special" names (starting with an underscore)
            if isfunction(val) and val.__name__[0] != '_':
                dct[key] = memoized(val)
        return type.__new__(cls, name, bases, dct)
装饰器是提前知道的,所以我不需要在对象本身中指定它。我也只关心方法,尽管出于我还不了解的原因,当
不可变时,对象的所有方法都是未绑定的。\uuuu new\uuuu
看到它们,因此它们是函数,而不是方法。我还排除了名称以下划线开头的方法:在内存化的情况下,您不想对像
\uuuu init\uuu
\uuu eq\uu
之类的方法执行任何操作