【问题标题】:Using super() in a property's setter method when using the @property decorator raises an AttributeError使用 @property 装饰器时在属性的 setter 方法中使用 super() 会引发 AttributeError
【发布时间】:2012-11-28 00:14:38
【问题描述】:

我对尝试覆盖子类中的属性时的行为感到有些困惑。

第一个示例设置了两个类,ParentChildParent 继承自 object,而 Child 继承自 Parent。属性a 是使用属性装饰器定义的。当child.a 的setter 方法被调用时,会引发AttributeError

在第二个示例中,通过使用 property() 函数而不是装饰器,一切都按预期工作。

谁能解释为什么行为不同?另外,是的,我知道 Child 中的 __init__ 定义是不需要的。

示例 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

示例 1 返回 - 引发属性错误

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'

示例 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

示例 2 返回 - 正常工作

a a
b bChild

【问题讨论】:

  • 我的第一个建议是在这种情况下不要使用装饰器形式。 (我发现它实际上很烦人,但对于只读属性)
  • 即便如此,还是有点奇怪。
  • 我在第 12 行 super(Child, self).a = val -- TypeError: super(type, obj): obj must be an instance or subtype of type 上收到示例 1 的不同错误。
  • 谢谢。当我复制和粘贴时,我以某种方式使用来自Child 的设置器作为Parent 中的设置器。现在应该修好了。
  • 即使您进行了更改,我也会遇到不同的错误。现在在第 20 行 super(Child, self).a = val -- AttributeError: 'super' object has no attribute 'a'

标签: python python-2.7


【解决方案1】:

super()返回的是代理对象,不是超类,不支持__set__()函数。

您可以在此处查看更多详细信息 Python super and setting parent class property 和此处 http://bugs.python.org/issue14965

【讨论】:

    猜你喜欢
    • 2018-09-06
    • 2019-11-09
    • 2013-02-26
    • 2019-12-21
    • 1970-01-01
    • 2021-11-27
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多