这个问题类似于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不起作用。
总而言之,描述符协议似乎与继承没有良好的交互...
答案 0 :(得分:9)
如果使用委托而不是继承,生活会更简单。这是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 )
是的,它感觉不到“干”。但是,它可以防止在将某些类“包装”到新功能中时遇到的许多问题,就像您正在尝试的那样。
答案 1 :(得分:4)
定义
def __init__(self):
self.foo = 5
Base
中的使foo
成为实例的成员(属性),而不是类的成员(属性)。 类 Base
不了解foo
,因此无法通过super()
调用等方式访问它。
然而,这不是必需的。当你实现
时foobar = Derived()
并且基类的__init__()
方法调用
self.foo = 5
这不会导致创建/覆盖属性,而是调用Derived
的setter,意思是
self.foo.fset(5)
因此self._foo = 5
。所以,如果你把
return 1 + self._foo
在你的吸气器中,你几乎可以得到你想要的东西。如果您需要在self.foo
的构造函数中设置Base
的值,请查看由_foo
正确设置的@foo.setter
。
答案 2 :(得分:1)
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
答案 3 :(得分:0)
一旦你拥有同名“foo”的财产,它就会覆盖名称'foo'的访问行为 唯一的出路似乎是你在 dict
中明确设置'foo'btw:我使用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
答案 4 :(得分:0)
老实说,这里要看的是你试图围绕一个简单的穷人设计扭曲你的代码。属性描述符处理'foo'属性的请求,你想完全绕过这些,这是错误的。你已经导致Base。 init 分配foobar._foo = 5,这也就是getter需要查看的地方。
class Base(object): def init (个体经营): 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