-->

如何避免__slots__字典查找?(How does __slots__ avoid a dict

2019-07-17 18:22发布

我听说__slots__使物体避免字典查找更快。 我的困惑来自于Python的是一个动态的语言。 在静态语言,我们避免对字典查找a.test做编译时优化保存在我们运行指令的索引。

现在,在Python中, a可以很容易地是具有字典或一组不同的属性的另一目的。 好像我们还是得做一个字典查找 - 唯一的区别似乎是,我们只需要一个字典类,而不是一本字典为每个对象。

有了这种理性,

  1. 如何__slots__避免字典查找?
  2. 难道插槽使访问对象更快?

Answer 1:

__slots__不(显著)加快访问属性:

>>> class Foo(object):
...     __slots__ = ('spam',)
...     def __init__(self):
...         self.spam = 'eggs'
... 
>>> class Bar(object):
...     def __init__(self):
...         self.spam = 'eggs'
... 
>>> import timeit
>>> timeit.timeit('t.spam', 'from __main__ import Foo; t=Foo()')
0.07030296325683594
>>> timeit.timeit('t.spam', 'from __main__ import Bar; t=Bar()')
0.07646608352661133

使用的目标__slots__节省内存 ; 代替使用.__dict__上的实例映射,类有描述符的对象为每一个在指定的属性__slots__和实例都分配了属性阉羊或不具有它们的实际值:

>>> class Foo(object):
...     __slots__ = ('spam',)
... 
>>> dir(Foo())
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'spam']
>>> Foo().spam
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: spam
>>> Foo.spam
<member 'spam' of 'Foo' objects>
>>> type(Foo.spam)
<type 'member_descriptor'>

所以Python仍然看类上的一个实例,每个属性访问Foo (找到描述符)。 任何未知属性(比如, Foo.ham )仍然将导致在Python翻翻类MRO要搜索的属性,包括字典搜索。 而且你还可以分配给附加属性:

>>> Foo.ham = 'eggs'
>>> dir(Foo)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'ham', 'spam']
>>> Foo().ham
'eggs'

创建类时创建槽描述符,和存取存储器分配给每个实例来存储和检索到相关联的值的参考(的存储器中的相同数据块,用于跟踪实例引用计数和一个返回参考对类对象)。 没有狭槽,为描述符__dict__用于访问所涉及的参考dict中相同的方式的对象。



Answer 2:

你实例很多相同的类的对象,真的永远不会改变他们有什么属性,它可能会加速程序,以及所有那些重复的字典高速缓存未命中呈现出真正的性能问题。

这是真正的一般情况下节省空间,有时节省了时间,其中的缓存是限制因素只是一个特例。

因此,它可能不会使访问一个对象更快,但可以加快访问相同类型的多个对象。

又见这个问题 。



文章来源: How does __slots__ avoid a dictionary lookup?