Python类继承的奇怪问题

时间:2014-06-26 16:12:15

标签: python inheritance attributes

我在Python中遇到类继承的问题,我似乎无法理解。这可能只是我对Python的经验不足。

我能够通过这个例子复制这个问题(我使用的是Python 3.3.4):

class R(object):
    def __init__(self, x, y, w, h):
        self._R = [x, y, w, h]

    @property
    def x(self):
        return self._R[0]
    @x.setter
    def x(self, value):
        self._R[0] = value
    @property
    def y(self):
        return self._R[1]
    @y.setter
    def y(self, value):
        self._R[1] = value
    @property
    def width(self):
        return self._R[2]
    @width.setter
    def width(self, value):
        self._R[2] = value
    @property
    def height(self):
        return self._R[3]
    @height.setter
    def height(self, value):
        self._R[3] = value


class Base(object):
    def __init__(self):
        self.pos = (0, 0)

class A(Base):
    def __init__(self):
        Base.__init__(self)
        self.rect = R(0, 0, 0, 0)

    @property
    def pos(self):
        return (self.rect.x, self.rect.y)
    @pos.setter
    def pos(self, value):
        (self.rect.x, self.rect.y) = value

class B(A):
    def __init__(self):
        A.__init__(self)
        self.foo = "bar"

o = B()
o.pos = (50, 50)

会产生以下错误:

Traceback (most recent call last):
  File "main.py", line 52, in <module>
    o = B()
  File "main.py", line 49, in __init__
    A.__init__(self)
  File "main.py", line 37, in __init__
    Base.__init__(self)
  File "main.py", line 33, in __init__
    self.pos = (0, 0)
  File "main.py", line 45, in pos
    (self.rect.x, self.rect.y) = value
AttributeError: 'B' object has no attribute 'rect'

2 个答案:

答案 0 :(得分:3)

您在设置 self.pos之前尝试使用self.rect setter

class Base(object):
    def __init__(self):
        self.pos = (0, 0)

class A(Base):
    def __init__(self):
        Base.__init__(self)
        self.rect = R(0, 0, 0, 0)

由于self.pos 上的A 是属性,因此尝试设置self.pos需要设置self.rect

向下移动Base.__init__(self)来电:

class A(Base):
    def __init__(self):
        self.rect = R(0, 0, 0, 0)
        Base.__init__(self)

现在self.rect是在Base.__init__尝试将值分配给self.pos时设置的。

答案 1 :(得分:2)

我想如果你把它改成这个

class A(Base):
    def __init__(self):
       self.rect = R(0, 0, 0, 0)
       Base.__init__(self)

它会起作用

问题是Base.__init__设置pos,这是引用self.rect的B的setter方法,但是在init调用之后才创建self.rect

所以要解决此问题,请在调用self.rect构造函数之前确保__init__存在