我的一位同事最近向我展示了以下会议:
>>> class Foo:
... __slots__ = ['x']
... def __init__(self):
... self.x = "x"
...
>>> f = Foo()
>>> f.x
'x'
>>> f.y = 1
>>> class Bar(object):
... __slots__ = ['x']
... def __init__(self):
... self.x = "x"
...
>>> b = Bar()
>>> b.x
'x'
>>> b.y = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Bar' object has no attribute 'y'
根据Python documentation,除非用户手动提供dict实例,否则定义__slots__
应该无法分配除插槽中指定的任何其他变量:
该文档没有说明明确需要从object
继承Bar
。
为什么会这样?
答案 0 :(得分:10)
确实如此,只是不是非常明确地说:
可以通过在新式类定义中定义__slots__来覆盖默认值。
在Python 2中,当你从object
继承时,你正在创建一个新式的类。如果你不这样做,那就是一个旧式的课程。
答案 1 :(得分:0)
正如杰米指出的那样,你想要一个新式的课程。这就是原因:
In [5]: import sys
In [6]: sys.getsizeof(f)
Out[6]: 36
In [7]: sys.getsizeof(b)
Out[7]: 28
In [8]: sys.getsizeof(f.__dict__)
Out[8]: 140
In [9]: sys.getsizeof(b.__dict__)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-891152de459e> in <module>()
----> 1 sys.getsizeof(b.__dict__)
AttributeError: 'Bar' object has no attribute '__dict__'
换句话说,您的Foo
类实际上并不使用插槽,它仍使用__dict__
来存储成员变量,因此f
的总大小为176字节且{{1 28字节(32位拱的数字)。这也是您可以分配b
。
据推测,您希望f.y = 1
减少内存使用量或强制对象的用户只触及时隙变量。 __slots__
同时做到了。 Bar
没有。