1

I'm getting an issue with class inheritance in Python that I can't seem to make sense of. It may just be my inexperience with Python.

I was able to replicate the issue with this example (I'm using 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)

which produces the following error:

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'
1
  • Off topic, but is 'class X(object)' still needed in Python3? I thought that was only necessary in Python2 in order to get the New classes. Commented Jun 27, 2014 at 0:13

2 Answers 2

3

You are trying to use the self.pos setter before self.rect is set:

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)

Because self.pos on A is a property, trying to set self.pos requires self.rect to already be set.

move the Base.__init__(self) call down:

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

Now self.rect is set by the time Base.__init__ tries to assign a value to self.pos.

Sign up to request clarification or add additional context in comments.

1 Comment

Ah, for some reason I thought that pos was being set through Base before the @property was actually in effect. Thanks for the great explanation
2

i think if you change it to this

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

it will work

the problem is that Base.__init__ sets pos , which is a setter method of B that references self.rect but self.rect is not created until after the init call.

so to resolve the issue, simple ensure that self.rect exists before calling __init__ constructor

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.