如果装饰器之前是 None,如何让装饰器 return a(缓存)属性?
How to have a decorator return a (cached) property iff it was previously None?
在一个 class 中,参数是可选的并且是其他计算的,我通常有类似
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
,但当且仅当它未设置为值≠None
...
可能不是最完美的解决方案,但这是我的做法:
import functools
#
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
在一个 class 中,参数是可选的并且是其他计算的,我通常有类似
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
,但当且仅当它未设置为值≠None
...
可能不是最完美的解决方案,但这是我的做法:
import functools
#
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