Python中的setter和getter

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python中的setter和getter相关的知识,希望对你有一定的参考价值。

参考技术A 🌰

这里需要注意的是对象里面有一个私有属性__name。其实这个私有属性在外面的对应的名字是 _类名__属性名。在这个例子里面就是 _TestClass__name。
既然这样,那么在外部调用 t.__name = "666" 那么就是直接给对象添加一个共有属性名字叫__name。

在 Python 中覆盖继承属性的 getter 和 setter

【中文标题】在 Python 中覆盖继承属性的 getter 和 setter【英文标题】:Overriding inherited properties’ getters and setters in Python 【发布时间】:2011-03-21 04:32:00 【问题描述】:

我目前正在使用@property 装饰器在我的几个类中实现“getter 和 setter”。我希望能够在子类中继承这些@property 方法。

我有一些 Python 代码(具体来说,我在 py3k 中工作)看起来有点像这样:

class A:
    @property
    def attr(self):
        try:
            return self._attr
        except AttributeError:
            return ''

class B(A):
    @property
    def attr(self):
        return A.attr   # The bit that doesn't work.

    @attr.setter
    def attr(self, value):
        self._attr = value

if __name__ == '__main__':
    b = B()
    print('Before set:', repr(b.attr))
    b.attr = 'abc'
    print(' After set:', repr(b.attr))

我已经用评论标记了不能使用的部分。我希望返回基类的 attr getter。 A.attr 返回一个属性对象(这可能非常接近我的需要!)。

编辑: 在收到 Ned 的以下回答后,我想出了一个更优雅的解决方案。

class A:
    @property
    def attr(self):
        try:
            return self._attr
        except AttributeError:
            return ''

class B(A):        
    @A.attr.setter
    def attr(self, value):
        self._attr = value

if __name__ == '__main__':
    b = B()
    print('Before set:', repr(b.attr))
    b.attr = 'abc'
    print(' After set:', repr(b.attr))

.setter 装饰器需要一个属性对象,我们可以使用@A.attr 获得它。这意味着我们不必在子类中再次声明该属性。

(这是在一天结束时解决问题与在一天开始时解决问题之间的区别!)

【问题讨论】:

我遇到了同样的问题,并且可以确认您的答案有效,但是哇,这是一个 $hitty 的“功能” - 添加超类名称链接!这对 python 来说是一个糟糕的设计。要么,要么“重新实现”该属性。两者都是糟糕的继承“解决方案”。 哇!谢谢@A.attr.setter。我先试了@super.attr.setter 这不行... 【参考方案1】:

我想你想要:

class B(A):
    @property
    def attr(self):
        return super(B, self).attr

你提到想要返回父类的getter,但是你需要调用getter,而不是返回它。

【讨论】:

这对我不起作用,但是,如果我打电话给super().attr,我会得到想要的效果。这是明智的做法吗? 啊,你是对的,因为父级的 .attr 不再可用作可调用的 getter,只能用作属性。 super() 是从父类访问同名属性的方法。为什么这是不明智的做法? 只是检查。我没有反对的理由。将您的回复更新为 super().attr 而不是 super(B, self).attr(),我会将其标记为已回答 :) 感谢您的提示! 你明白了!我会为那个大的绿色复选标记做几乎任何事情! :) 虽然我只使用了super().attr 而不是super(B, self).attr。然而,两者似乎都有效。【参考方案2】:

为了覆盖 python 2 中的设置器,我这样做了:

class A(object):
    def __init__(self):
        self._attr = None

    @property
    def attr(self):
        return self._attr

    @attr.setter
    def attr(self, value):
        self._attr = value


class B(A):
    @A.attr.setter
    def attr(self, value):
        # Do some crazy stuff with `value`
        value = value[0:3]
        A.attr.fset(self, value)

要了解A.attr.fset 的来源,请参阅property 类的文档: https://docs.python.org/2/library/functions.html#property

【讨论】:

有趣的是,B 没有A 继承getter。如果B 仅继承自object,则B.attr.fget 将返回<function Foo.baz at 0x123456789>。我担心A.attr.fset 现在被分配了一个用户定义的函数。 A.attr.fset 仍然是 None,而 B.attr.fset<function B.baz at 0x987654321>。因此,覆盖任何属性的可访问性成员,首先创建属性的副本。至少,这似乎是正在发生的事情。 我特别喜欢您展示如何仅覆盖 setter。我不知道该怎么做,这让我对 setter 装饰器有了更深入的了解。 @TylerCrompton。这就是你必须做@propertyname.setter 的全部原因:属性是不可变的对象,通常,如果你定义了一个getter 和一个setter,你就已经创建了两个属性对象,第一个被丢弃了。我相信您在最初发表评论五年后才意识到这一点,但我会留在这里留给后代。 我经常看到属性getter有get_attr这样的名字,setter有set_attr这样的名字的约定,我遵循这个约定。但是,当我测试您的代码时,它在子类 B(A) 中的 setter 方法与属性同名时才有效。换句话说,如果我在您的代码中将def attr(self, value) 替换为def set_attr(self, value),那么它将停止工作(它不会覆盖父类的属性设置器)。这似乎有点违反直觉。是不是bug? 这行得通。但是,如果我还想覆盖父母的吸气剂,添加类似@A.attr.setter\\def attr(self) 的东西由于某种原因不起作用。如果它出现在@A.attr.setter 部分之后,则忽略设置器部分。反之亦然。为什么?

以上是关于Python中的setter和getter的主要内容,如果未能解决你的问题,请参考以下文章

详解JavaScript对象中的getter和setter

详解JavaScript对象中的getter和setter

JS中的getter和setter

java中的setter和getter有啥意义? [复制]

Swift 中的 Getter 和 Setter

Flutter 中的 Getter/Setter 使用 Android Studio