辞書
リストでは位置によって要素を検索できます。しかし、名前で検索したいことが多くあります。「3番目の要素を取得」ではなく、「ハナコのスコアを取得」のように。辞書はデータをキーと値のペアとして格納します:位置ではなくキーによって値を検索します。
辞書を作成する
各キーと値の間にコロン、ペアの間にカンマを置き、波括弧で囲みます。キーはほぼ常に文字列です。値は何でもよく、数値、文字列、他のリスト、さらには他の辞書も使えます。
player = {
"name": "ハナコ",
"score": 87,
"level": 5,
"alive": True,
}値にアクセスする
キーを使って角括弧で値を取得します。キーが存在しない場合、PythonはKeyErrorを発生させます。キーが存在するかわからない場合は.get()を使います: クラッシュせずNoneを返すか、指定したデフォルト値を返します。
player = {"name": "ハナコ", "score": 87}
player["name"] # "ハナコ"
player["score"] # 87
player["lives"] # KeyError (キーが存在しない)player.get("score") # 87
player.get("lives") # None (エラーなし、デフォルトでNoneを返す)
player.get("lives", 3) # 3 (キーがない場合のデフォルトを指定).get()はキーが欠落している可能性がある場合に安全です:
count = inventory.get("arrows", 0) # "arrows"が辞書にない場合は0追加と更新
角括弧でキーに代入します。キーがすでに存在する場合、値は置き換えられます。まだ存在しない場合、新しいエントリーが作成されます。.update()を使うと、他の辞書全体を一度にマージできます。
player = {"name": "ハナコ", "score": 87}
player["score"] = 92 # 既存を更新
player["level"] = 5 # 新しいキーを追加extras = {"level": 5, "alive": True}
player.update(extras) # extrasのキーで追加/上書き項目を削除する
エントリーを削除する4つの方法があります。.pop()はキーを削除し、値を返します。デフォルト付きの.pop()は、キーが存在しないかもしれないときに安全です。delはキーを削除しますが戻り値はありません。.clear()は辞書全体を空にします。
player = {"name": "ハナコ", "score": 87, "level": 5}
player.pop("level") # "level"を削除し、5を返す
player.pop("lives", None) # 安全なpop、キーがなければNoneを返す
del player["score"] # "score"を削除、戻り値なし
player.clear() # すべてを削除デフォルト付きの.pop()は、存在しないかもしれないキーを削除する最も安全な方法です。
反復処理
3つのビューを使って辞書のさまざまな部分をループできます。辞書をそのまま反復処理するとキーが得られます。.values()は値を返します。.items()は両方を一度に返し、最もよく使います: 各ペアを2つの名前にアンパックして、きれいで読みやすいループを書けます。
player = {"name": "ハナコ", "score": 87, "level": 5}
for key in player: # キーを反復処理(最も一般的)
print(key)
for key in player.keys(): # 同上、明示的なキービュー
print(key)
for value in player.values(): # 値だけ
print(value)
for key, value in player.items(): # 両方、最も便利
print(f"{key}: {value}").items()は最もよく使うものです。各ペアを2つの名前にアンパックすることで、ループが読みやすくなります。
メンバーシップをチェックする
inはキーが辞書に存在するかどうかをチェックします。値はチェックせず、キーだけです。何かが存在しないかチェックするにはnot inを使います。
player = {"name": "ハナコ", "score": 87}
"name" in player # True
"lives" in player # False
"lives" not in player # Trueinはキーだけをチェックします。値をチェックするにはin player.values()を使いますが、ほとんど必要ありません。
ネストした辞書
値自体が辞書になることもあります。これは、複数のレベルを持つ構造化データを表現する方法です: 統計セクションを持つプレイヤー、サブセクションを持つ設定ファイルなど。2組の角括弧でネストされた値にアクセスします: 最初は外側のキーを選び、2番目は内側のキーを選びます。
users = {
"はなこ": {"score": 87, "level": 5},
"たろう": {"score": 74, "level": 3},
}
users["はなこ"]["score"] # 87
users["たろう"]["level"] # 3連鎖した角括弧でアクセスします。深くネストした構造では扱いにくくなるので、できる限りネストは浅く保ってください。
setdefault
.setdefault()はキーが存在すればその値を読み取り、存在しなければデフォルト値を設定して、値を返します。キーを存在させたいが、すでに存在する場合は上書きしたくないときに便利です。
inventory = {}
inventory.setdefault("arrows", 0) # "arrows": 0を設定、0を返す
inventory.setdefault("arrows", 10) # "arrows"はすでに存在、変更なし、0を返すこれは、最初にキーの存在をチェックせずにグループ化された構造を構築するのに便利です:
groups = {}
for name, team in players:
groups.setdefault(team, []).append(name)collections.defaultdictとCounter
標準ライブラリには、よくあるパターンを自動的に処理する2つの辞書サブクラスがあります。defaultdictは欠落したキーに対してデフォルト値を作成するので、KeyErrorが発生しません。Counterはシーケンス内で各項目が何度現れるかを数え、結果を辞書として返します。
collectionsのインポート
defaultdictとCounterは標準ライブラリからインポートする必要があります。インポートはモジュールの章で扱います。
from collections import defaultdict
groups = defaultdict(list)
for name, team in players:
groups[team].append(name) # teamが新しくてもKeyErrorなしfrom collections import Counter
words = ["cat", "dog", "cat", "bird", "cat", "dog"]
counts = Counter(words)
# Counter({'cat': 3, 'dog': 2, 'bird': 1})
counts.most_common(2) # [('cat', 3), ('dog', 2)]Counterは、「ループで物を数える」決まり文句を多く節約してくれます。
実践例
スコアトラッカーを構築し、すべてのエントリーを含むサマリーを表示する例:
scores = {"ハナコ": 87, "タロウ": 74, "サクラ": 92, "ケンタ": 55}
total = sum(scores.values())
average = total / len(scores)
print(f"Players: {len(scores)}")
print(f"Average: {average:.1f}")
print(f"Highest: {max(scores.values())}")
print(f"Lowest: {min(scores.values())}")
print()
for name, score in scores.items():
print(f" {name}: {score}")
