简体   繁体   English

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

[英]Why must I explicitly inherit object for slots to work as advertised?

A colleague of mine recently showed me the following session: 我的一位同事最近向我展示了以下会议:

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

According to the Python documentation , defining __slots__ should make it impossible to assign any other variables than the ones specified in slots, unless the user provides a dict instance manually: 根据Python文档 ,定义__slots__应该使得除了用户手动提供dict实例之外,不可能分配除插槽中指定的任何其他变量:

The documentation says nothing about an explicit need to inherit from object like Bar does. 文档没有提到像Bar那样继承object的明确需求。

Why does this happen? 为什么会这样?

It does say it, just not very explicitly: 它确实说,只是不明确:

The default can be overridden by defining __slots__ in a new-style class definition. 可以通过在新样式类定义中定义__slots__来覆盖默认值。

In Python 2, when you inherit from object , you're creating a new-style class. 在Python 2中,当你从object继承时,你正在创建一个新式的类。 If you don't, it's an old-style class. 如果你不这样做,那就是一个旧式的课程。

As Jamie pointed out, you want a new-style class. 正如杰米指出的那样,你想要一个新式的课程。 here's why: 这是为什么:

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

In other words, your Foo class doesn't actually use slots, it still uses __dict__ to store member variables, thus total size of f is 176 bytes and b 28 bytes (figures for 32-bit arch). 换句话说,你的Foo类实际上并没有使用槽,它仍然使用__dict__来存储成员变量,因此f总大小是176字节和b 28字节(32位拱的数字)。 It is also why you can assign fy = 1 . 这也是你可以指定fy = 1

Presumably you want __slots__ to reduce memory usage or to force users of your objects to touch only slotted variables. 据推测,您希望__slots__减少内存使用量或强制对象的用户只触及插槽变量。 Bar does both. Bar做到了。 Foo does neither. Foo既没有。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM