为什么我必须显式继承插槽的对象才能像宣传的那样工作?

时间:2013-07-16 17:51:03

标签: python

我的一位同事最近向我展示了以下会议:

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

为什么会这样?

2 个答案:

答案 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没有。