Reputation: 4928
I am a little confused by the behavior when attempting to overwrite a property in a subclass.
The first example sets up two classes, Parent
and Child
. Parent
inherits from object
, while Child
inherits from Parent
. The property a
is defined using the property decorator. When child.a
's setter method is called, an AttributeError
is raised.
In the second example, by using the property()
function rather than the decorator, everything works as would be expected.
Can anyone shed some light on why the behavior differs? Also, yes, I know that the __init__
definition in Child is not needed.
@property
class Parent(object):
def __init__(self):
self._a = 'a'
@property
def a(self):
return self._a
@a.setter
def a(self, val):
self._a = val
class Child(Parent):
def __init__(self):
super(Child, self).__init__()
@property
def a(self):
return super(Child, self).a
@a.setter
def a(self, val):
val += 'Child'
super(Child, self).a = val
p = Parent()
c = Child()
print p.a, c.a
p.a = 'b'
c.a = 'b'
print p.a, c.a
a a
Traceback (most recent call last):
File "testsuper.py", line 26, in <module>
c.a = 'b'
File "testsuper.py", line 20, in a
super(Child, self).a = val
AttributeError: 'super' object has no attribute 'a'
Using property()
class Parent(object):
def __init__(self):
self._a = 'a'
def _get_a(self):
return self._a
def _set_a(self, val):
self._a = val
a = property(_get_a, _set_a)
class Child(Parent):
def __init__(self):
super(Child, self).__init__()
def _get_a(self):
return super(Child, self)._get_a()
def _set_a(self, val):
val = val+'Child'
super(Child, self)._set_a(val)
a = property(_get_a, _set_a)
p = Parent()
c = Child()
print p.a, c.a
p.a = 'b'
c.a = 'b'
print p.a, c.a
a a
b bChild
Upvotes: 19
Views: 7625
Reputation: 438
super()
returns a proxy object, not a superclass, and it doesn't support the function __set__()
.
And you can see more details here Python super and setting parent class property and here http://bugs.python.org/issue14965.
Upvotes: 13