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的主要内容,如果未能解决你的问题,请参考以下文章