__slots__如何避免字典查找? [英] How does __slots__ avoid a dictionary lookup?
问题描述
我听说__slots__
通过避免字典查找来加快对象的速度.我的困惑来自Python是一种动态语言.在静态语言中,我们通过进行编译时优化将索引保存在我们运行的指令中,从而避免了对a.test
的字典查找.
I've heard that __slots__
makes objects faster by avoiding a dictionary lookup. My confusion comes from Python being a dynamic language. In a static language, we avoid a dictionary lookup for a.test
by doing a compile-time optimisation to save the index in the instruction we run.
现在,在Python中,a
可以很容易地成为另一个具有字典或不同属性集的对象.似乎我们仍然需要进行字典查找-唯一的区别似乎是我们只需要为该类使用一个字典,而不是为每个对象使用字典.
Now, in Python, a
could just as easily be another object that has a dictionary or a different set of attributes. It seems like we'll still have to do a dictionary lookup - the only difference seems to be that we only need one dictionary for the class, rather than a dictionary for each object.
有了这种理性,
-
__slots__
如何避免字典查找? - 插槽是否可以更快地访问对象?
- How does
__slots__
avoid a dictionary lookup? - Does slots make accessing objects faster?
推荐答案
__slots__
不能(显着)加速属性访问:
__slots__
does not (significantly) speed up attribute access:
>>> 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__
中命名的每个属性和实例分配了是否属性的实例,它们具有实际值:
The goal of using __slots__
is to save memory; instead of using a .__dict__
mapping on the instance, the class has descriptors objects for each and every attribute named in __slots__
and instances have the attribute assigned wether or not they have an actual value:
>>> 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来搜索该属性,其中包括字典搜索.而且,您仍然可以将其他属性分配给 class :
So python still has to look at the class for each attribute access on an instance of Foo
(to find the descriptor). Any unknown attribute (say, Foo.ham
) will still result in Python looking through the class MRO to search for that attribute, and that includes dictionary searches. And you can still assign additional attributes to the class:
>>> 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
对象的引用.
The slot descriptors are created when the class is created, and access memory assigned to each instance to store and retrieve a reference to the associated value (the same chunk of memory that tracks instance reference counts and a reference back to the class object). Without slots, a descriptor for __dict__
is used accessing a reference to a dict
object in the same manner.
这篇关于__slots__如何避免字典查找?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!