首页 文章

如果在派生类中覆盖此属性,如何调用基类的属性?

提问于
浏览
73

我正在改变我的一些类别,从广泛使用吸气剂和制定者到使用更多的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

5 回答

  • 4

    您可能认为可以调用属性调用的基类函数:

    class FooBar(Foo):
    
        @property
        def bar(self):
            # return the same value
            # as in the base class
            return Foo.bar(self)
    

    虽然这是我认为最明显的尝试 - it does not work because bar is a property, not a callable.

    但是属性只是一个对象,使用getter方法来查找相应的属性:

    class FooBar(Foo):
    
        @property
        def bar(self):
            # return the same value
            # as in the base class
            return Foo.bar.fget(self)
    
  • 82

    Super应该做的诀窍:

    return super().bar
    

    在Python 2.x中,您需要使用更详细的语法:

    return super(FooBar, self).bar
    
  • 17

    有一种使用 super 的替代方法,它不需要显式引用基类名称 .

    基类A:

    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
    

    在B中,访问父类A的属性getter:

    正如其他人已经回答的那样,它是:

    super(B, self).prop
    

    或者在Python 3中:

    super().prop
    

    这将返回属性的getter返回的值,而不是getter本身,但它足以扩展getter .

    在B中,访问父类A的属性设置器:

    我到目前为止看到的最佳建议如下:

    A.prop.fset(self, value)
    

    我相信这个更好:

    super(B, self.__class__).prop.fset(self, value)
    

    在这个例子中,两个选项都是等价的,但使用super的优点是独立于 B 的基类 . 如果 B 继承自 C 类并且还扩展了属性,则不必更新 B 的代码 .

    B扩展A属性的完整代码:

    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)
    

    一个警告:

    除非你的属性没有setter,否则你必须在 B 中定义setter和getter,即使你只改变其中一个的行为 .

  • 42

    尝试

    @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
    
  • -1
    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()
    

    (除非我遗漏了你的解释)

相关问题