繁体   English   中英

__slots__如何避免字典查找?

[英]How does __slots__ avoid a dictionary lookup?

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

现在,在Python中, a可以很容易地成为另一个具有字典或不同属性集的对象。 看起来我们仍然需要进行字典查找 - 唯一的区别似乎是我们只需要一个类的字典,而不是每个对象的字典。

有了这个理性,

  1. __slots__如何避免字典查找?
  2. 插槽是否可以更快地访问对象?

__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对象的引用。

它可能会加速一个程序,你可以在其中实例化同一类的大量对象,真正永远不会更改它们具有的属性,并且所有这些重复字典上的缓存未命中都会带来真正的性能问题。

这实际上只是一般情况的特例,其中节省空间有时也节省了时间,其中缓存是限制因素。

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

另见这个问题

暂无
暂无

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

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