15

__slots__辞書検索を避けることでオブジェクトが高速になると聞いたことがあります。私の混乱は、Python が動的言語であることから来ています。a.test静的言語では、コンパイル時の最適化を実行して実行する命令にインデックスを保存することで 、辞書検索を回避します。

現在、Python ではa、辞書または異なる属性セットを持つ別のオブジェクトを簡単に作成できます。ディクショナリ ルックアップを行う必要があるようです。唯一の違いは、各オブジェクトのディクショナリではなく、クラスのディクショナリが 1 つだけ必要であることです。

この理性で、

  1. __slots__辞書検索を回避するにはどうすればよいですか?
  2. スロットはオブジェクトへのアクセスを高速化しますか?
4

2 に答える 2

19

__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

于 2013-01-02T08:37:51.307 に答える
6

同じクラスの多くのオブジェクトをインスタンス化するプログラムを高速化する可能性があり、それらが持つ属性をまったく変更せず、重複したすべての辞書でキャッシュミスが発生すると、実際のパフォーマンスの問題が発生します。

これは、キャッシュが制限要因である場合に、スペースを節約すると時間節約されることがある一般的な状況の特殊なケースです。

そのため、おそらく1 つのオブジェクトへのアクセスが速くなることはありませんが、同じタイプの多くのオブジェクトへのアクセスが速くなる可能性があります。

この質問も参照してください。

于 2013-01-02T07:57:22.883 に答える