你想利用
self.value
属性的名称,以及在封面下用于存储该属性的属性的名称。这没道理,你得给它起个不同的名字。由于该属性应为“private”,并且只能通过属性访问,因此通常需要使用下划线前缀。
换句话说,在例子中做完全相同的事情。
the docs for
property
.
当然还有
if not value:
必须更改才能通过
self
,不是同名的局部变量。
class A:
_value = None
@property
def value(self):
if not self._value:
result = <do some external call>
self._value = result
return self._value
另一个选择是使用一个为您这样做的库。正如martijn pieters在评论中指出的,
cached-property
确切地告诉你你想要什么。而且它在各种你可能从未想过的边缘情况下都经过了测试和健壮,比如线程和异步。而且它还有很好的文档和可读的源代码,来解释它是如何工作的。
不管怎样,现在还不清楚为什么
_value = None
是正确的。
_值=无
在类定义中创建
类属性
命名
_value
,由类的所有实例共享。
self._value = result
在方法体不更改类属性的情况下,它创建
实例属性
同名。
实例属性
阴影
类属性。也就是说,当你试图访问
self._value
在
if
和
return
语句,它查找实例属性,如果不存在类属性,则返回到类属性。所以,类属性
None
值作为实例属性的默认值。
为了提供默认的属性值,这是一个非常常见的习惯用法,但在某些情况下可能会混淆(例如,具有可变值)。
做同样的事情的另一种方法是强制实例总是有一个
γ值
属性,通过在
__new__
或
__init__
方法:
class A:
def __init__(self):
self._value = None
@property
def value(self):
if not self._value:
result = <do some external call>
self._value = result
return self._value
虽然乍一看这有点冗长和复杂(并且需要知道
爱因斯坦
,它确实避免了混淆类和实例属性的可能性,因此如果您与新手共享代码,他们更有可能遵循它。
或者,您可以使用
getattr
查看属性是否存在,因此不需要回退类属性或
爱因斯坦
,但这通常不是你想做的。
退一步,你甚至可以替换
财产
用一个描述符替换第一个查找函数,但是如果你不知道它是什么意思(即使在读了
HowTo
),你可能也不想这么做。