これは何を意味するのでしょうか?
ディクショナリキーとして受け入れられない値のタイプは、オブジェクトIDではなく値によって比較されるリストまたはディクショナリまたはその他の可変タイプを含む値のみです。これは、ディクショナリを効率的に実装するには、キーのハッシュ値を一定に保つ必要があるためです。
タプルの場合でも、値によって比較が行われると思います。
これは何を意味するのでしょうか?
ディクショナリキーとして受け入れられない値のタイプは、オブジェクトIDではなく値によって比較されるリストまたはディクショナリまたはその他の可変タイプを含む値のみです。これは、ディクショナリを効率的に実装するには、キーのハッシュ値を一定に保つ必要があるためです。
タプルの場合でも、値によって比較が行われると思います。
キーとしての可変オブジェクトの問題は、辞書を使用するときに、IDを確認することはめったにないということです。たとえば、次のような辞書を使用する場合:
a = "bob"
test = {a: 30}
print(test["bob"])
私たちはそれが機能することを期待しています-2番目の文字列"bob"
はと同じではないかもしれませんが、a
それは同じ値であり、それが私たちが気にしていることです。これは、同等の2つの文字列が同じハッシュを持つため、dict
(ハッシュマップとして実装された)がこれらの文字列を非常に効率的に見つけることができるため、機能します。
この問題は、リストをキーとして使用するときに発生します。次の場合を想像してみてください。
a = ["bob"]
test = {a: 30}
print(test[["bob"]])
これ以上これを行うことはできません。リストのハッシュはその値ではなく、リストのインスタンス(別名(id(a) != id(["bob"))
)に基づいているため、比較は機能しません。
Pythonには、リストのハッシュを変更する(ハッシュマップの効率を損なう)か、単にIDを比較する(ほとんどの場合役に立たない)かを選択できます。Pythonは、これらの特定の可変キーを禁止して、値がIDではなく値と同等であると人々が期待する微妙ではあるが一般的なバグを回避します。
ドキュメントには、可変性と値比較可能という 2 つの異なる要素が混在しています。それらを分離しましょう。
ID で比較する不変オブジェクトは問題ありません。どのオブジェクトについても、ID は決して変更できません。
値で比較する不変オブジェクトは問題ありません。不変オブジェクトの値は変更できません。これにはタプルが含まれます。
ID で比較する可変オブジェクトは問題ありません。どのオブジェクトについても、ID は決して変更できません。
値で比較する可変オブジェクトは受け入れられません。変更可能なオブジェクトの値が変更される可能性があり、辞書が無効になります。
一方、あなたの言い回しは Mapping Types ( 4.10 in Python 3.3または5.8 in Python 2.7、どちらも次のように言っています:
ディクショナリのキーはほとんど任意の値です。ハッシュ可能でない値、つまり、リスト、辞書、またはその他の変更可能な型 (オブジェクト ID ではなく値で比較される) を含む値は、キーとして使用できません。
とにかく、ここで重要な点は、ルールが「ハッシュ可能ではない」ということです。「変更可能な型 (オブジェクト ID ではなく値で比較される)」は、もう少し詳しく説明するためのものです。オブジェクト ID による比較とオブジェクト ID によるハッシュが常に同じであるとは限りません (必要なのは、id が等しい場合、ハッシュが等しいということだけです)。
あなたが投稿したバージョンの「辞書の効率的な実装」に関する部分は、混乱を招くだけです(これがおそらくリファレンスドキュメントにない理由です)。明日誰かがリストを辞書キーとして保存する効率的な方法を思いついたとしても、言語はそれを許しません。
ハッシュは、オブジェクトの一意のコードを計算する方法です。このコードは、同じオブジェクトに対して常に同じです。hash('test')
たとえば is です2314058222102390712
。a = 'test'; もそうです。hash(a)
= 2314058222102390712
.
内部的に辞書の値は、指定した変数ではなく、ハッシュによって検索されます。リストは変更可能です。リストのハッシュが定義されている場合、リストが変更されるたびに変更されます。したがって、python の設計ではリストをハッシュしません。したがって、リストを辞書のキーとして使用することはできません。
タプルは不変であるため、チューブにはハッシュ eG hash((1,2))
=があります3713081631934410656
。値ではなくハッシュを比較するa
ことで、タプルがタプルと等しいかどうかを比較できます。(1,2)
これは、2 つの値ではなく 1 つの値のみを比較する必要があるため、より効率的です。