辞書はPython 3.6以降で注文されますか?
これらは挿入順になっています[1]。Python 3.6以降、PythonのCPython実装では、辞書は挿入された項目の順序を記憶しています。これはPython 3.6の実装の詳細と見なされます。Pythonの他の実装全体で保証されてOrderedDict
いる挿入順序(および他の順序付けされた動作[1])が必要な場合に使用する必要があります。
Python 3.7以降、これは実装の詳細ではなくなり、代わりに言語機能になります。GvRによるpython-devメッセージから:
そうしてください。「口述は挿入順序を保つ」が判決です。ありがとう!
これは単にあなたがそれに依存できることを意味します。他のPythonの実装も、Python 3.7の準拠実装にしたい場合は、挿入順の辞書を提供する必要があります。
要素の順序を維持しながら、Python 3.6
辞書の実装は以前のものよりどのようにパフォーマンスが向上しますか[2]。
基本的に、2つのアレイを保持することにより。
最初の配列はdk_entries
、ディクショナリの(タイプPyDictKeyEntry
)のエントリを、挿入された順序で保持します。順序を維持することは、新しい項目が常に最後に挿入される追加のみの配列であることによって実現されます(挿入順序)。
2番目のはdk_indices
、dk_entries
配列のインデックス(つまり、の対応するエントリの位置を示す値dk_entries
)を保持します。この配列はハッシュテーブルとして機能します。キーがハッシュされるdk_indices
と、格納されているインデックスの1つになり、対応するエントリがインデックスによってフェッチされますdk_entries
。インデックスのみが保持されるため、この配列のタイプはディクショナリの全体的なサイズに依存しますint8_t
(タイプ(1
バイト)からint32_t
/ int64_t
(4
/ 8
バイト)32
/ / 64
ビットビルドの範囲)
以前の実装では、タイプPyDictKeyEntry
とサイズのスパース配列をdk_size
割り当てる必要がありました。残念なことに、その配列はパフォーマンス上の理由で2/3 * dk_size
いっぱいになることを許可されていなかったため、多くの空のスペースも生じました。(と空きスペースは、まだ持っていたサイズを!)。PyDictKeyEntry
必要なエントリー(挿入されたエントリー)のみが保管され、タイプintX_t
(X
dictサイズに応じて)2/3 * dk_size
のスパース配列がいっぱいになるため、これは現在のところ当てはまりません。空のスペースがタイプPyDictKeyEntry
からに変更されましたintX_t
。
したがって、明らかに、タイプのスパース配列を作成することは、s PyDictKeyEntry
を格納するためのスパース配列よりもはるかに多くのメモリを要求しint
ます。
興味があれば、この機能に関するPython-Devでの会話全体を見ることができます。
レイモンドヘッティンガーによる最初の提案では、使用されたデータ構造の視覚化を見て、アイデアの要点を捉えることができます。
たとえば、辞書:
d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}
現在、[キーハッシュ、キー、値]として保存されています:
entries = [['--', '--', '--'],
[-8522787127447073495, 'barry', 'green'],
['--', '--', '--'],
['--', '--', '--'],
['--', '--', '--'],
[-9092791511155847987, 'timmy', 'red'],
['--', '--', '--'],
[-6480567542315338377, 'guido', 'blue']]
代わりに、データは次のように編成する必要があります。
indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
視覚的にわかるように、元の提案では、衝突を減らしてルックアップを高速化するために、多くのスペースが基本的に空になっています。新しいアプローチでは、インデックスでスパース性を実際に必要な場所に移動することで、必要なメモリを削減します。
[1]:OrderedDictが存在する場合、「ordered」はdict
オブジェクトが提供しない追加の動作を示唆するため、「挿入順序」ではなく「挿入順序」と言います。OrderedDictsは可逆的であり、順序に敏感なメソッドを提供し、主に順序に敏感な等価性テストを提供します(==
、!=
)。dict
■現在、これらの動作/メソッドは提供されていません。
[2]:新しいディクショナリの実装は、よりコンパクトに設計されることにより、より優れたメモリのパフォーマンスを発揮します。これが主なメリットです。速度に関しては、その違いはそれほど大きくはありません。新しい辞書がわずかな回帰(たとえば、キールックアップ)をもたらす可能性がある場所もあれば、パフォーマンスのブーストが存在するはずです(反復とサイズ変更が頭に浮かびます)。
導入されたコンパクトさにより、全体的に、特に実際の状況での辞書のパフォーマンスが向上します。