3

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

>>> 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 文档,除非用户手动提供 dict 实例,否则定义__slots__应该使得无法分配除槽中指定的变量之外的任何其他变量:

该文档没有说明明确需要从objectlike继承Bar

为什么会这样?

4

2 回答 2

10

它确实这么说,只是不是很明确:

可以通过在新样式类定义中定义 __slots__ 来覆盖默认值。

在 Python 2 中,当您从 继承时object,您正在创建一个新样式的类。如果你不这样做,这是一个老式的类。

于 2013-07-16T17:53:27.907 回答
0

正如 Jamie 指出的那样,你想要一个新式的课程。原因如下:

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 字节和b28 字节(32 位拱门的数字)。这也是您可以分配f.y = 1.

大概你想__slots__减少内存使用或强制你的对象的用户只接触有槽的变量。Bar两者都做。Foo也没有。

于 2013-10-16T17:40:30.197 回答