代码之家  ›  专栏  ›  技术社区  ›  UncleZeiv

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

  •  75
  • UncleZeiv  · 技术社区  · 15 年前

    我将把我的一些类从广泛使用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
    
    5 回复  |  直到 6 年前
        1
  •  84
  •   CivFan    9 年前

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

    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)
    
        2
  •  44
  •   Pankrat    13 年前

    Super 应该这样做:

    return super().bar
    

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

    return super(FooBar, self).bar
    
        3
  •  17
  •   RasmusN    6 年前

    有另一种用途 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 . 如果 从一个 C 类同时扩展属性,您不必更新 的代码。

    扩展A属性的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)
    

    一个警告:

    除非属性没有setter,否则必须在 即使你只改变其中一个的行为。

        4
  •  4
  •   workmad3    15 年前

    尝试

    @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
    
        5
  •  -1
  •   shylent    15 年前
        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()
    

    (除非我在你的解释中遗漏了什么)