python 为什么 setter 是首选?
python why is a setter preferred?
属性 装饰器是 "protect" 属性的一种很好的方式,人们希望设置一次,就再也不会改变。我通常这样处理(顺便说一句,遵循建议):
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'
就足够了,尽管很明显这是处理问题的最糟糕方法。
我能想到的最好的解释是来自作者的消息 "you should not change this attribute but if you really want to, there is a mechanism to do it without changing a 'protected' attribute"。但是,python 并没有真正保护属性。
那么,有什么意义呢,哪个更 pythonic,为什么?
如果setter
和getter
只是直接读写受保护的变量,那么它们是没有意义的,使用它不是Pythonic;它只是在每次访问的 property
开销上浪费时间。该属性应该只设为 public 并删除 属性。
属性的优点是当您需要用更强大的东西替换那个简单的 public 属性时,因为您可以制作一个 属性 继续 act 就像使用属性的代码一样,但也执行额外的工作。除非你有额外的工作,否则如果你允许它被写入,请坚持使用该属性。
注意:从技术上讲,getter 和 setter
并非 100% 等同于属性,因为没有 deleter
,它在行为上与原始属性并不相同。但是在 API 中强制执行不可删除性是愚蠢的;在第三方 class 实例(或几乎任何实例)的随机属性上四处调用 del obj.attr
的开发人员理应得到他们的回报,您不应该以牺牲减慢并使正常使用模式复杂化。
如果您在 getter 或 setter 中没有做任何特殊的事情,那么没有充分理由使用 属性 是正确的。但是,如果您 想做一些特别的事情(比如验证新值,或以某种方式规范化它们),那么它就很有意义了。
例如,这个 class 的 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
属性 装饰器是 "protect" 属性的一种很好的方式,人们希望设置一次,就再也不会改变。我通常这样处理(顺便说一句,遵循建议
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'
就足够了,尽管很明显这是处理问题的最糟糕方法。
我能想到的最好的解释是来自作者的消息 "you should not change this attribute but if you really want to, there is a mechanism to do it without changing a 'protected' attribute"。但是,python 并没有真正保护属性。
那么,有什么意义呢,哪个更 pythonic,为什么?
如果setter
和getter
只是直接读写受保护的变量,那么它们是没有意义的,使用它不是Pythonic;它只是在每次访问的 property
开销上浪费时间。该属性应该只设为 public 并删除 属性。
属性的优点是当您需要用更强大的东西替换那个简单的 public 属性时,因为您可以制作一个 属性 继续 act 就像使用属性的代码一样,但也执行额外的工作。除非你有额外的工作,否则如果你允许它被写入,请坚持使用该属性。
注意:从技术上讲,getter 和 setter
并非 100% 等同于属性,因为没有 deleter
,它在行为上与原始属性并不相同。但是在 API 中强制执行不可删除性是愚蠢的;在第三方 class 实例(或几乎任何实例)的随机属性上四处调用 del obj.attr
的开发人员理应得到他们的回报,您不应该以牺牲减慢并使正常使用模式复杂化。
如果您在 getter 或 setter 中没有做任何特殊的事情,那么没有充分理由使用 属性 是正确的。但是,如果您 想做一些特别的事情(比如验证新值,或以某种方式规范化它们),那么它就很有意义了。
例如,这个 class 的 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