Unc*_*eiv 81 python inheritance overloading properties descriptor
我正在改变我的一些类别,从广泛使用吸气剂和制定者到更加诡计多端的财产使用.
但现在我被卡住了,因为我之前的一些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
Run Code Online (Sandbox Code Playgroud)
Dav*_*eau 92
您可能认为可以调用属性调用的基类函数:
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return Foo.bar(self)
Run Code Online (Sandbox Code Playgroud)
虽然这是我认为最明显的尝试 - 它不起作用,因为bar是属性,而不是可调用的.
但是属性只是一个对象,使用getter方法查找相应的属性:
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return Foo.bar.fget(self)
Run Code Online (Sandbox Code Playgroud)
Pan*_*rat 47
超级应该做的伎俩:
return super().bar
Run Code Online (Sandbox Code Playgroud)
在Python 2.x中,您需要使用更详细的语法:
return super(FooBar, self).bar
Run Code Online (Sandbox Code Playgroud)
Max*_* R. 19
有一个替代使用super,不需要显式引用基类名称.
class A(object):
def __init__(self):
self._prop = None
@property
def prop(self):
return self._prop
@prop.setter
def prop(self, value):
self._prop = value
class B(A):
# we want to extend prop here
pass
Run Code Online (Sandbox Code Playgroud)
正如其他人已经回答的那样,它是:
super(B, self).prop
Run Code Online (Sandbox Code Playgroud)
或者在Python 3中:
super().prop
Run Code Online (Sandbox Code Playgroud)
这将返回属性的getter返回的值,而不是getter本身,但它足以扩展getter.
我到目前为止看到的最佳建议如下:
A.prop.fset(self, value)
Run Code Online (Sandbox Code Playgroud)
我相信这个更好:
super(B, self.__class__).prop.fset(self, value)
Run Code Online (Sandbox Code Playgroud)
在这个例子中,两个选项都是等价的,但是使用super具有独立于基类的优点B.如果B要继承C类也扩展属性,则不必更新B代码.
class B(A):
@property
def prop(self):
value = super(B, self).prop
# do something with / modify value here
return value
@prop.setter
def prop(self, value):
# do something with / modify value here
super(B, self.__class__).prop.fset(self, value)
Run Code Online (Sandbox Code Playgroud)
除非你的属性没有setter,否则你必须定义setter和getter,B即使你只改变其中一个的行为.
对马克西姆的答案的一些小改进:
__class__避免写入B。请注意,self.__class__是 的运行时类型self,但__class__ without self是封闭类定义的名称。super()是 的简写super(__class__, self)。__set__而不是fset. 后者特定于propertys,但前者适用于所有类似属性的对象(描述符)。class B(A):
@property
def prop(self):
value = super().prop
# do something with / modify value here
return value
@prop.setter
def prop(self, value):
# do something with / modify value here
super(__class__, self.__class__).prop.__set__(self, value)
Run Code Online (Sandbox Code Playgroud)