python为什么选择setter?

时间:2017-09-29 01:38:38

标签: python properties setter

物业装饰师是一个很好的方式来保护"属性想要设置一次而永远不会再改变。我通常以这种方式处理这个问题(顺便说一句,遵循建议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并没有真正保护属性。

那么,重要的是什么呢?为什么呢?

2 个答案:

答案 0 :(得分:4)

如果settergetter只是直接写和阅读受保护变量,那么它们就没有意义了,使用它不是Pythonic;它只是在每次访问的property开销上浪费时间。该属性应该公开并删除属性。

属性的优点是当你需要用更强大的东西替换那个简单的公共属性时,因为你可以为使用该属性的代码创建一个继续 act 的属性,但也要做额外的工作。除非你有额外的工作,否则坚持使用属性,如果你仍然允许它被写入。

注意:从技术上讲,getter和setter不是100%等效于属性,因为没有deleter,它与raw属性的行为不同。但是,在API中强制执行不可删除性是愚蠢的;那些在第三方类实例(或几乎任何实例)的随机属性上调用del obj.attr的开发人员应该得到他们正在发生的事情,你不应该以放慢速度和复杂化为代价来防范这些废话。正常使用模式。

答案 1 :(得分:3)

如果您在getter或setter中没有做任何特殊操作,那么您无需使用属性。但是,如果您想要做一些特别的事情(比如验证新值,或者以某种方式对它们进行规范化),那么它就很有意义。

例如,此类的foo属性将始终夹在01之间(非数字值会立即导致错误):

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