我正在改变我的一些类别,从大量使用吸气剂和制定者到使用更多的pythonic属性。
但是现在我被卡住了,因为我之前的一些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
答案 0 :(得分:87)
您可能认为可以调用属性调用的基类函数:
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return Foo.bar(self)
虽然这是最明显的尝试,我认为 - 它不起作用,因为bar是属性,而不是可调用。
但是属性只是一个对象,使用getter方法来查找相应的属性:
class FooBar(Foo):
@property
def bar(self):
# return the same value
# as in the base class
return Foo.bar.fget(self)
答案 1 :(得分:44)
答案 2 :(得分:18)
使用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
正如其他人已经回答的那样,它是:
super(B, self).prop
或者在Python 3中:
super().prop
这将返回属性的getter返回的值,而不是getter本身,但它足以扩展getter。
我目前看到的最佳建议如下:
A.prop.fset(self, value)
我相信这个更好:
super(B, self.__class__).prop.fset(self, value)
在此示例中,两个选项都是等效的,但使用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)
除非你的财产没有设置者,否则你必须在B
中定义setter和getter,即使你只改变其中一个的行为。
答案 3 :(得分:4)
试
@property
def bar:
return super(FooBar, self).bar
虽然我不确定python是否支持调用基类属性。属性实际上是一个可调用对象,它使用指定的函数进行设置,然后在类中替换该名称。这很容易意味着没有超级功能可用。
您可以随时切换语法以使用property()函数:
class Foo(object):
def _getbar(self):
return 5
def _setbar(self, a):
print a
bar = property(_getbar, _setbar)
class FooBar(Foo):
def _getbar(self):
# return the same value
# as in the base class
return super(FooBar, self)._getbar()
def bar(self, c):
super(FooBar, self)._setbar(c)
print "Something else"
bar = property(_getbar, _setbar)
fb = FooBar()
fb.bar = 7
答案 4 :(得分:1)
Maxime's answer的一些小改进:
__class__
避免编写B
。请注意,self.__class__
是self
的运行时类型,但是__class__
without self
是封闭类定义的名称。 super()
是super(__class__, self)
的简写。__set__
代替fset
。后者特定于property
,但前者适用于所有类似属性的对象(描述符)。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)
答案 5 :(得分:0)
您可以使用以下模板:
class Parent():
def __init__(self, value):
self.__prop1 = value
#getter
@property
def prop1(self):
return self.__prop1
#setter
@prop1.setter
def prop1(self, value):
self.__prop1 = value
#deleter
@prop1.deleter
def prop1(self):
del self.__prop1
class Child(Parent):
#getter
@property
def prop1(self):
return super(Child, Child).prop1.__get__(self)
#setter
@prop1.setter
def prop1(self, value):
super(Child, Child).prop1.__set__(self, value)
#deleter
@prop1.deleter
def prop1(self):
super(Child, Child).prop1.__delete__(self)
注意!必须一起重新定义所有属性方法。如果不想重新定义所有方法,请改用以下模板:
class Parent():
def __init__(self, value):
self.__prop1 = value
#getter
@property
def prop1(self):
return self.__prop1
#setter
@prop1.setter
def prop1(self, value):
self.__prop1 = value
#deleter
@prop1.deleter
def prop1(self):
del self.__prop1
class Child(Parent):
#getter
@Parent.prop1.getter
def prop1(self):
return super(Child, Child).prop1.__get__(self)
#setter
@Parent.prop1.setter
def prop1(self, value):
super(Child, Child).prop1.__set__(self, value)
#deleter
@Parent.prop1.deleter
def prop1(self):
super(Child, Child).prop1.__delete__(self)
答案 6 :(得分:-2)
class Base(object):
def method(self):
print "Base method was called"
class Derived(Base):
def method(self):
super(Derived,self).method()
print "Derived method was called"
d = Derived()
d.method()
(除非我遗漏了你的解释)