如果以前是None,如何让装饰器返回(缓存)属性?

时间:2015-03-10 10:58:05

标签: python caching decorator nonetype

在一个参数是可选的并且另外计算的类中,我通常有类似

的东西
class Demo(object):
    def __init__(self, value=None):
        self._value = value

    @property
    def value(self):
        if self._value is None:
            # some calculations to get value
            self._value = value
        return self._value

这是相当嘈杂的恕我直言,类似于记忆序言。我喜欢像

这样的东西
    @property_if_None
    def value(self):
        # some calculations to get value
        return value

value不是可选的,但根本没有设置我使用@functools.lru_cached,但这不起作用。


当然,我可以简单地将__init__更改为

    def __init__(self, value=None):
        if value is None:
            # some calculations to get value
        self.value = value

但我们假设# some calculations to get value很长,应该有自己的功能 - 我更愿意拨打value(),从而有效地使value成为@property 1}},但当且仅当它没有设置为值≠None ...

1 个答案:

答案 0 :(得分:0)

可能不是最完美的解决方案,但这是我的目标:

import functools

# http://stackoverflow.com/a/28961925/321973
def property_if_None_generator(f, cached=False):
    @functools.wraps(f)
    def wrapped(self):
        value = self.__getattribute__('_' + f.__name__)
        if value is not None:
            return value
        else:
            return f(self)
    if cached:
        wrapped = functools.lru_cache()(wrapped)
    return property(wrapped)

property_if_None = lambda f: property_if_None_generator(f, cached=False)
cached_property_if_None = lambda f: property_if_None_generator(f, cached=True)
然后问题的例子会变成

class Demo(object):
    def __init__(self, value=None):
        self._value = value

    @chached_property_if_None
    def value(self):
        # some calculations to get value
        return value