物业装饰师是一个很好的方式来保护"属性想要设置一次而永远不会再改变。我通常以这种方式处理这个问题(顺便说一句,遵循建议here):
self._name = 'foo'
@property
def name(self):
return self._name
因此尝试直接设置名称会产生AttributeError。
但是,我经常看到以下模式:
@name.setter
def name(self, value):
self._name = value
@property
def name(self):
return self._name
这似乎有点反直觉,因为它能够完全实现我想要避免的,并且需要额外的编码,即理论上
self.name = 'bar'
就足够了,尽管很明显这是解决这个问题的最糟糕方式。
我能想出的最好的解释就像来自作者的消息说"你不应该改变这个属性,但是如果你真的想要,有一种机制可以在不改变&#39的情况下做到这一点。 ;保护'属性&#34 ;.但是,python并没有真正保护属性。
那么,重要的是什么呢?为什么呢?
答案 0 :(得分:4)
如果setter
和getter
只是直接写和阅读受保护变量,那么它们就没有意义了,使用它不是Pythonic;它只是在每次访问的property
开销上浪费时间。该属性应该公开并删除属性。
属性的优点是当你需要用更强大的东西替换那个简单的公共属性时,因为你可以为使用该属性的代码创建一个继续 act 的属性,但也要做额外的工作。除非你有额外的工作,否则坚持使用属性,如果你仍然允许它被写入。
注意:从技术上讲,getter和setter
不是100%等效于属性,因为没有deleter
,它与raw属性的行为不同。但是,在API中强制执行不可删除性是愚蠢的;那些在第三方类实例(或几乎任何实例)的随机属性上调用del obj.attr
的开发人员应该得到他们正在发生的事情,你不应该以放慢速度和复杂化为代价来防范这些废话。正常使用模式。
答案 1 :(得分:3)
如果您在getter或setter中没有做任何特殊操作,那么您无需使用属性。但是,如果您做想要做一些特别的事情(比如验证新值,或者以某种方式对它们进行规范化),那么它就很有意义。
例如,此类的foo
属性将始终夹在0
和1
之间(非数字值会立即导致错误):
class Foo:
_foo = 1.0
@foo
def probability(self):
return self._foo
@foo.setter
def foo(self, value):
if value < 0:
value = 0
elif value > 1:
value = 1
self._foo = value
一个简单的setter的例子,但是复杂的getter可能是这样的(推迟可能不需要的昂贵的初始化):
class Foo:
_foo = None
def initialize_foo(self):
self._foo = some_expensive_calculation()
@property
def foo(self):
if self._foo is None:
self.initialize_foo() # need the default value
return self._foo
@foo.setter
def foo(self, value):
self._foo = value