简体   繁体   English

使用@property装饰器时在属性的setter方法中使用super()会引发AttributeError

[英]Using super() in a property's setter method when using the @property decorator raises an AttributeError

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 . 第一个示例设置两个类ParentChild Parent inherits from object , while Child inherits from Parent . Parentobject继承,而ChildParent继承。 The property a is defined using the property decorator. 使用属性装饰器定义属性a When child.a 's setter method is called, an AttributeError is raised. child.a的setter方法时,将引发AttributeError

In the second example, by using the property() function rather than the decorator, everything works as would be expected. 在第二个示例中,通过使用property()函数而不是装饰器,一切都会按预期进行。

Can anyone shed some light on why the behavior differs? 谁能阐明为什么行为不同? Also, yes, I know that the __init__ definition in Child is not needed. 另外,是的,我知道不需要Child中的__init__定义。

Example 1 - Using @property 示例1-使用@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 示例1 return-引发属性错误

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() 示例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 示例2返回-正常工作

a a
b bChild

super() returns a proxy object, not a superclass, and it doesn't support the function __set__() . super()返回一个代理对象,而不是超类,并且不支持__set__()函数。

And you can see more details here Python super and setting parent class property and here http://bugs.python.org/issue14965 . 并且您可以在此处的Python super和设置父类属性以及此处的http://bugs.python.org/issue14965中看到更多详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM