将装饰器应用于属性g

2024-06-16 09:34:57 发布

您现在位置:Python中文网/ 问答频道 /正文

根据this previous question关于默认情况下记忆类的所有方法的回答,我将使用以下元类:

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)
            elif hasattr(val, 'fget'):
                # It's a property; we currently can't memoize these
                pass
        return type.__new__(cls, name, bases, dct)

这个元类的作用是将decorator memoized应用于类中的所有函数和方法。唯一的问题是它不适用于属性。(使用这个元类的类被视为不可变的,所以我只担心这里的只读属性)

from time import sleep

class Foo(object):
    __metaclass__ = Immutable

    @property
    def slow_calculation(self):
        sleep(5)    # simulate an intensive calculation
        return 4

然后slow_calculation就不会被记忆,每次调用它都会有5秒钟的延迟,而不仅仅是第一次。你知道吗

问题是property()返回的是property对象,而不是函数,因此元类__new__中的isfunction测试不会捕获属性。如您所见,我添加了一个查找属性的测试,但是我不知道如何将memoized装饰器应用于属性getter fget。我想也许我可以说

elif hasattr(val, 'fget'):
    val.fget = memoized(val.fget)
    dct[key] = val

但在这种情况下我

Traceback (most recent call last):
  [...]
  File "utils.py", line 54, in __new__
    val.fget = memoized(val.fget)
TypeError: Error when calling the metaclass bases
    readonly attribute

有没有其他方法可以将decorator应用于属性getter?你知道吗


Tags: 方法记忆keynamenew属性情况property