如果基类的属性在派生类中被覆盖,如何调用该属性?
我正在将我的一些类从广泛使用 getter 和 setter 改为更Python 化地使用属性。
但现在我陷入了困境,因为我以前的一些 getter 或 setter 会调用基类的相应方法,然后执行其他操作。 但是如何通过属性来实现这一点呢? 如何调用父类中的属性getter或setter?
当然,仅调用属性本身就会产生无限递归。
class Foo(object):
@property
def bar(self):
return 5
@bar.setter
def bar(self, a):
print a
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return self.bar # --> recursion!
@bar.setter
def bar(self, c):
# perform the same action
# as in the base class
self.bar = c # --> recursion!
# then do something else
print 'something else'
fb = FooBar()
fb.bar = 7
I'm changing some classes of mine from an extensive use of getters and setters to a more pythonic use of properties.
But now I'm stuck because some of my previous getters or setters would call the corresponding method of the base class, and then perform something else. But how can this be accomplished with properties? How to call the property getter or setter in the parent class?
Of course just calling the attribute itself gives infinite recursion.
class Foo(object):
@property
def bar(self):
return 5
@bar.setter
def bar(self, a):
print a
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return self.bar # --> recursion!
@bar.setter
def bar(self, c):
# perform the same action
# as in the base class
self.bar = c # --> recursion!
# then do something else
print 'something else'
fb = FooBar()
fb.bar = 7
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您可能认为您可以调用由属性调用的基类函数:
虽然这是最明显的尝试,但我认为 - 它不起作用,因为 bar 是一个属性,而不是可调用的。
但是属性只是一个对象,有一个 getter 方法来查找相应的属性:
You might think you could call the base class function which is called by property:
Though this is the most obvious thing to try I think - it does not work because bar is a property, not a callable.
But a property is just an object, with a getter method to find the corresponding attribute:
super()
应该解决这个问题:在 Python 2.x 中,您需要使用更详细的语法:
super()
should do the trick:In Python 2.x you need to use the more verbose syntax:
还有一种使用
super
的替代方法,它不需要显式引用基类名称。基类A:
在B中,访问父类的属性getter A:
正如其他人已经回答的那样,它是:
或者在Python 3中:
这返回属性的getter返回的值,而不是getter本身,但它足以延长吸气剂。
在 B 中,访问父类 A 的属性 setter:
迄今为止我见过的最好的建议如下:
我相信这个更好:
在这个例子中,两个选项是等效的,但使用 super 的优点是独立于
B
的基类。 如果B
从同时扩展该属性的C
类继承,则无需更新B
的代码。B 扩展 A 属性的完整代码:
一个警告:
除非您的属性没有 setter,否则您必须在
B
中定义 setter 和 getter,即使您只更改其中之一的行为他们。There is an alternative using
super
that does not require to explicitly reference the base class name.Base class A:
In B, accessing the property getter of the parent class A:
As others have already answered, it's:
Or in Python 3:
This returns the value returned by the getter of the property, not the getter itself but it's sufficient to extend the getter.
In B, accessing the property setter of the parent class A:
The best recommendation I've seen so far is the following:
I believe this one is better:
In this example both options are equivalent but using super has the advantage of being independent from the base classes of
B
. IfB
were to inherit from aC
class also extending the property, you would not have to updateB
's code.Full code of B extending A's property:
One caveat:
Unless your property doesn't have a setter, you have to define both the setter and the getter in
B
even if you only change the behaviour of one of them.对 Maxime 的回答的一些小改进:
__class__
避免编写B
。 请注意,self.__class__
是self
的运行时类型,但__class__
withoutself
> 是封闭类定义的名称。super()
是super(__class__, self)
的简写。__set__
而不是fset
。 后者特定于属性,但前者适用于所有类似属性的对象(描述符)。Some small improvements to Maxime's answer:
__class__
to avoid writingB
. Note thatself.__class__
is the runtime type ofself
, but__class__
withoutself
is the name of the enclosing class definition.super()
is a shorthand forsuper(__class__, self)
.__set__
instead offset
. The latter is specific toproperty
s, but the former applies to all property-like objects (descriptors).尝试一下
虽然我不确定python是否支持调用基类属性。 属性实际上是一个可调用对象,它使用指定的函数进行设置,然后替换类中的该名称。 这很容易意味着没有可用的超级功能。
不过,您始终可以切换语法以使用 property() 函数:
try
Although I'm not sure if python supports calling the base class property. A property is actually a callable object which is set up with the function specified and then replaces that name in the class. This could easily mean that there is no super function available.
You could always switch your syntax to use the property() function though:
您可以使用以下模板:
注意! 所有属性方法必须一起重新定义。 如果不想重新定义所有方法,请使用以下模板:
You can use the following template:
Note! All of the property methods must be redefined together. If do not want to redefine all methods, use the following template instead:
(除非我在你的解释中遗漏了一些东西)
(that is unless I am missing something from your explanation)