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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.