__slots__如何避免字典查找? [英] How does __slots__ avoid a dictionary lookup?

查看:104
本文介绍了__slots__如何避免字典查找?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我听说__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.

有了这种理性,

  1. __slots__如何避免字典查找?
  2. 插槽是否可以更快地访问对象?
  1. How does __slots__ avoid a dictionary lookup?
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆