Using super() in a property's setter method when using the @property decorator raises an AttributeError
python, python-2.7
Solution
`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.
Problem
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. Example 1 - Using `@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 ``` Example 1 return - Raises an attribute error ``` 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' ``` Example 2 - `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 ``` Example 2 return - Works correctly ``` a a b bChild ```