Python,__slots__,继承和类变量==>属性是只读错误

时间:2011-04-22 17:05:16

标签: python slots

我有一棵拥有数十万个节点的大树,而我正在使用__slots__来减少内存消耗。我刚刚发现了一个非常奇怪的错误并修复了它,但我不明白我看到的行为。

这是一个简化的代码示例:

class NodeBase(object):
    __slots__ = ["name"]
    def __init__(self, name):
        self.name = name

class NodeTypeA(NodeBase):
    name = "Brian"
    __slots__ = ["foo"]

然后执行以下命令:

>>> node = NodeTypeA("Monty")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
AttributeError: 'NodeTypeA' object attribute 'name' is read-only

如果未定义NodeTypeA.name,则没有错误(旁注:该属性存在错误,并且没有理由在那里)。如果永远不会定义NodeTypeA.__slots__,也没有错误,因此它有一个__dict__

我不明白的是:为什么超类中存在类变量会干扰在​​子类的槽中设置实例变量?

有人可以解释为什么这种组合会导致object attribute is read-only错误吗?我知道我的例子是人为的,并且不太可能是真实程序中的故意,但这并不会使这种行为变得不那么奇怪。

谢谢,
乔纳森

1 个答案:

答案 0 :(得分:17)

一个较小的例子:

class C(object):
    __slots__ = ('x',)
    x = 0

C().x = 1

documentation on slots状态一度:

  通过为每个变量名创建描述符(实现描述符),在类级别实现

__slots__。因此,类属性不能用于为__slots__定义的实例变量设置默认值;否则,class属性将覆盖描述符赋值。

当使用__slots__时,对插槽属性的属性分配需要通过为插槽属性创建的描述符。隐藏子类中的描述符会导致Python无法找到设置属性所需的例程。 Python仍然可以看到属性存在(因为它找到了遮蔽描述符的对象),因此它报告该属性是只读的。