問題の歴史:
辞書(dict)はPythonの基本データ型の1つで、「キー-バリュー」構造を表します。辞書は最初のPythonから存在していましたが、その内部実装や動作の特性は常に改善されてきました(たとえば、Python 3.7では挿入順序が保証されます)。
問題:
辞書の動作を理解することは、効率的なコーディングのために重要です。詳細を知らないと、変更可能な型をキーとして使用する際や、ネストされた辞書をコピーする際、さらには標準でない操作をする際にバグが発生することがあります。
解決策:
辞書はハッシュテーブルとして実装されており、キーは必ずハッシュ可能である必要があります(不変)。キーによるバリューへのアクセスはほぼO(1)で動作しますが、いくつかの条件下では特異性が生じます—たとえば、衝突があったり、大量のデータを扱う場合です。
コード例:
person = {'name': 'Alice', 'age': 30} person['city'] = 'Moscow' print(person['name']) # Alice
主な特性:
リスト(list)をdictのキーとして使用できますか?
いいえ、リストは変更可能であり、ハッシュ可能ではありません。リストを使用しようとするとエラーが発生します。
d = {} d[[1, 2, 3]] = 'value' # TypeError: unhashable type: 'list'
2つの内容が同じタプルをキーとして使用した場合、どうなりますか?
両方のタプルが同じデータを持ち、かつ不変であれば、等しいと見なされ、辞書内のキーが一致します:
t1 = (1, 2) t2 = (1, 2) d = {t1: 'a'} print(d[t2]) # 'a'
コピーすると辞書の要素の順序は変更されますか?
Python 3.7以降では順序は保持されます。それ以前のバージョンでは、順序は保証されません。
d1 = {'a': 1, 'b': 2} d2 = dict(d1) print(list(d2)) # ['a', 'b']
dict.get()をNoneチェックなしで使うことは、値が== Noneの場合に予期しないエラーを引き起こす可能性があります。プログラマーがリストをキーとして保存し、tupleとlistがPythonでは同等であると誤信し、「unhashable type」の例外を受け取りました。
メリット:
すぐに何かを「試す」ことができ、任意の構造を使用できます。
デメリット:
ランタイムエラー、データ処理時のバグ。
不変(ハッシュ可能)オブジェクトのみをキーとして使用し、タプルが変更可能な要素を含まないように設計されています。
メリット:
キーによる検索の迅速性、構造の信頼性、容易な処理とコピー。
デメリット:
データが複雑な場合、構造を不変形式に変換するための追加の処理が必要です(たとえば、タプル内でのシリアル化)。