首页 文章

如果基类的数据成员被覆盖为派生类中的属性,如何调用它?

提问于
浏览
5

此问题类似于this other one,区别在于基类中的数据成员未被描述符协议包装 .

换句话说,如果我用派生类中的属性覆盖其名称,我该如何访问基类的成员?

class Base(object):
    def __init__(self):
        self.foo = 5

class Derived(Base):
    def __init__(self):
        Base.__init__(self)

    @property
    def foo(self):
        return 1 + self.foo # doesn't work of course!

    @foo.setter
    def foo(self, f):
        self._foo = f

bar = Base()
print bar.foo

foobar = Derived()
print foobar.foo

请注意,我还需要定义一个setter,否则在基类中分配self.foo不起作用 .

总而言之,描述符协议似乎与继承没有良好的交互...

5 回答

  • 1

    一旦你拥有相同名称的属性'foo'它会覆盖名称'foo'的访问行为只有出路似乎你在 dict 中明确设置'foo'

    顺便说一句:我使用python 2.5因此不得不改变代码

    class Base(object):
        def __init__(self):
            self.foo = 5
    
    class Derived(Base):
        def __init__(self):
            Base.__init__(self)
    
        def g_foo(self):
            return 1 + self.__dict__['foo'] # works now!
    
        def s_foo(self, f):
            self.__dict__['foo'] = f
            self._foo = f
    
        foo = property(g_foo, s_foo)
    
    bar = Base()
    print bar.foo
    
    foobar = Derived()
    print foobar.foo
    
  • 9

    老实说,这里要看的是你已经造成基地了 . init 指定foobar._foo = 5,这也就是吸气剂需要看的地方 .

    class Base(object):def init (self):self.foo = 5

    class Derived(Base):
      def __init__(self):
        Base.__init__(self)
    
      @property
      def foo(self):
        return 1 + self._foo # DOES work of course!
    
      @foo.setter
      def foo(self, f):
        self._foo = f
    
    bar = Base()
    print bar.foo
    
    foobar = Derived()
    print foobar.foo
    
  • 4
    class Foo(object):
        def __new__(cls, *args, **kw):
            return object.__new__(cls, *args, **kw)
    
        def __init__(self):
            self.foo = 5
    
    class Bar(Foo):
        def __new__(cls, *args, **kw):
            self = object.__new__(cls, *args, **kw)
            self.__foo = Foo.__new__(Foo)
            return self
    
        def __init__(self):
            Foo.__init__(self)
    
        @property
        def foo(self):
            return 1 + self.__foo.foo
    
        @foo.setter
        def foo(self, foo):
            self.__foo.foo = foo
    
    bar = Bar()
    bar.foo = 10
    print bar.foo
    
  • 0

    定义

    def __init__(self):
        self.foo = 5
    

    in Base 使 foo 成为实例的成员(属性),而不是类的成员(属性) . 类 Base 不知道 foo ,因此无法通过 super() 调用等方式访问它 .

    但是,这不是必需的 . 当你实现

    foobar = Derived()
    

    和基类调用的 __init__() 方法

    self.foo = 5
    

    这不会导致创建/覆盖属性,而是在 Derived 的setter被调用,意思是

    self.foo.fset(5)
    

    因此 self._foo = 5 . 所以,如果你把

    return 1 + self._foo
    

    在你的吸气器中,你几乎可以得到你想要的东西 . 如果你需要在 Base 的构造函数中设置 self.foo 的值,只需查看 _foo 正确设置的 _foo .

  • 0

    如果使用委托而不是继承,生活会更简单 . 这是Python . 您没有义务继承 Base .

    class LooksLikeDerived( object ):
        def __init__( self ):
            self.base= Base()
    
        @property
        def foo(self):
            return 1 + self.base.foo # always works
    
        @foo.setter
        def foo(self, f):
            self.base.foo = f
    

    但是Base的其他方法呢?您复制了 LooksLikeDerived 中的名称 .

    def someMethodOfBase( self, *args, **kw ):
        return self.base.someMethodOfBase( *args **kw )
    

    是的,它感觉不到“干” . 但是,它可以防止在将某些类“包装”到新功能中时遇到的许多问题,就像您正在尝试的那样 .

相关问题