辞書(dict)は、データをキーと値のペアで関連付けて管理するためのデータ構造です。
リストが位置(インデックス)でアクセスするのに対し、辞書はキーで直接探せるため、設定値、検索テーブル、名称と値の対応関係などに向いています。
「名前→点数」「商品コード→在庫数」「設定名→値」といった用途で威力を発揮します。
辞書(dict)とは?キーと値で管理する基本
Pythonの辞書の役割とリストとの違い
辞書は、キーから値を瞬時に取り出すための構造です。
リストは順序とインデックス重視ですが、辞書は意味のあるキーで管理するため、意図が明確になりやすいです。
例えば名前から点数を知りたいとき、リストでは全体を探す必要がありますが、辞書ならキーで直接アクセスできます。
以下はリストと辞書の典型的な違いです。
- リストは
scores[0]
のように位置でアクセスします。要素の順序が意味を持ちます。 - 辞書は
scores["Alice"]
のようにキーでアクセスします。順序ではなく対応関係が意味を持ちます。
簡単な例を示します。
# 名前をキー、点数を値として管理する辞書
scores = {"Alice": 92, "Bob": 78, "Charlie": 85}
# キーで直接アクセスできる(高速で簡潔)
print(scores["Alice"]) # 92
92
使いどころ(検索・設定・マッピング)
辞書は次のような場面で効果的です。
コード全体の可読性も高まります。
- 検索テーブル(文字から数字、拡張子からMIMEタイプなど)
- 設定値の保存(設定名→値)
- ラベルや名前のマッピング(ユーザーID→プロフィール)
「キーの集合」から「値の集合」へ対応付けると考えると理解しやすいです。
辞書の作り方({} と dict())
辞書はリテラルの{}
またはコンストラクタのdict()
で作れます。
# 1) リテラルで作成
person = {"name": "Alice", "age": 30}
# 2) 空の辞書を作って後から追加
empty = {}
# 3) dict() でキーワード引数から作成(キーは文字列に限る)
config = dict(debug=True, retries=3)
# 4) (キー, 値)のペア列から作成
pairs = [("host", "localhost"), ("port", 5432)]
db = dict(pairs)
# 5) 辞書内包表記で変換しながら作成
squares = {n: n*n for n in range(3)} # {0:0, 1:1, 2:4}
print(person)
print(config)
print(db)
print(squares)
{'name': 'Alice', 'age': 30}
{'debug': True, 'retries': 3}
{'host': 'localhost', 'port': 5432}
{0: 0, 1: 1, 2: 4}
辞書の基本操作(追加・取得・更新・削除)
要素を追加/更新する(dict[key] と update)
辞書名[キー] = 値で追加または更新できます。
すでに存在するキーに代入すると上書きになります。
まとめて変更したい場合はupdate()
が便利です。
settings = {"theme": "light", "lang": "ja"}
# 追加
settings["timeout"] = 10 # 新しいキーを追加
# 更新(同じキーに代入すると上書き)
settings["theme"] = "dark"
# まとめて更新(update)。既存キーは上書き、新規キーは追加
settings.update({"lang": "en", "autosave": True})
print(settings)
{'theme': 'dark', 'lang': 'en', 'timeout': 10, 'autosave': True}
値を取得する([] と get の違い)
[]
アクセスはキーがないとKeyErrorになります。
安全に取り出したいときはget()
を使い、見つからない場合のデフォルト値を与えます。
user = {"name": "Bob", "age": 20}
# [] は必須のキーに向く。存在しないと KeyError
print(user["name"]) # 正常
# print(user["email"]) # KeyError: 'email' (コメント解除でエラー)
# get は見つからないと None(または指定デフォルト)を返す
print(user.get("email")) # None
print(user.get("email", "N/A")) # "N/A" を返す
Bob
None
N/A
[]は必須のキー、getは任意のキーという使い分けが基本です。
要素を削除する(del・pop・clear)
単一のキー削除はdel d[key]
またはpop(key)
を使います。
pop
は削除した値を返すので、同時に取得したいときに便利です。
全削除はclear()
です。
stock = {"A": 10, "B": 5, "C": 0}
# 値を取り出しつつ削除
b = stock.pop("B") # b は 5
print("popped:", b)
print(stock)
# del は値を返さない
del stock["C"]
print(stock)
# 安全に pop したい場合はデフォルト値を渡す
x = stock.pop("X", 0) # X が無ければ 0 を返す
print("popped X:", x)
# 全削除
stock.clear()
print(stock)
popped: 5
{'A': 10, 'C': 0}
{'A': 10}
popped X: 0
{}
キーの存在確認(in と get)
キーの存在を確認するにはin
が明確です。
get
は値が0
や空文字""
のときも「偽」と判定されるため、存在確認にはinを推奨します。
data = {"count": 0, "name": ""}
print("count" in data) # True
print("missing" in data) # False
# get は存在しないと None を返す。値が0や""のときの判定に注意
print(data.get("count") is not None) # True (存在する)
print(bool(data.get("name"))) # False (空文字は偽だがキーは存在)
True
False
True
False
初期化パターン(空・初期値付き)
空で作って後から埋めるほか、全キーを同じ値で始めたいときはdict.fromkeys()
が使えます。
また、辞書内包表記で柔軟に初期化できます。
# 空で開始
d1 = {}
# fromkeys で同一初期値(注意: ミュータブル値は共有される)
fields = ["host", "port", "user"]
d2 = dict.fromkeys(fields, None) # 全て None で初期化
# 辞書内包表記で個別の初期値を計算
defaults = {k: (0 if k == "port" else "") for k in fields}
print(d1)
print(d2)
print(defaults)
{}
{'host': None, 'port': None, 'user': None}
{'host': '', 'port': 0, 'user': ''}
走査と便利メソッドの使い方
ループで回す(for・items)
辞書をループする基本は2通りです。
キーだけ回すか、items()
でキーと値を同時に受け取ります。
prices = {"apple": 120, "banana": 90, "orange": 150}
# キーだけループ
for name in prices:
print(name, prices[name]) # 値は辞書参照で取得
print("---")
# キーと値を同時にループ
for name, price in prices.items():
print(name, price)
apple 120
banana 90
orange 150
---
apple 120
banana 90
orange 150
keys()/values()/items()の使い分け
keys()
はキーのビュー、values()
は値のビュー、items()
は(キー, 値)のビューを返します。ビューは動的で、辞書の変更を反映します。- 値だけ集めて合計するなどは
values()
、キーと値を一緒に処理するならitems()
が読みやすいです。
scores = {"A": 10, "B": 20, "C": 30}
total = sum(scores.values())
pairs = list(scores.items()) # リスト化して並べ替えやスライスに使える
print(total)
print(pairs)
60
[('A', 10), ('B', 20), ('C', 30)]
デフォルト値で安全に取り出す(get・setdefault)
get()
は読み取り専用、setdefault()
は「無ければ入れて返す」という挙動です。
カウントやグルーピングの初期化に役立ちます。
text = "banana"
counter = {}
# setdefault を使って初期化しながらカウント
for ch in text:
counter.setdefault(ch, 0) # 無ければ 0 をセット
counter[ch] += 1
print(counter) # {'b': 1, 'a': 3, 'n': 2}
# get なら読み取り専用でデフォルトを返す
x = counter.get("x", 0)
print("count(x) =", x)
{'b': 1, 'a': 3, 'n': 2}
count(x) = 0
辞書を結合する(update・|)
辞書をマージするには破壊的なupdate()
と、新しい辞書を返す|
(パイプ演算子、Python 3.9+)があります。
重複キーは右側が優先されます。
base = {"host": "localhost", "port": 8000}
override = {"port": 8080, "debug": True}
# 1) 破壊的に結合
merged1 = base.copy()
merged1.update(override)
# 2) 新しい辞書を返す(元は変えない)
merged2 = base | override
print("base:", base)
print("merged1:", merged1)
print("merged2:", merged2)
base: {'host': 'localhost', 'port': 8000}
merged1: {'host': 'localhost', 'port': 8080, 'debug': True}
merged2: {'host': 'localhost', 'port': 8080, 'debug': True}
updateは左辺を変更、|は新しい辞書という違いを覚えると安全です。
注意点とベストプラクティス
キーに使える型(ハッシュ可能)
辞書のキーはハッシュ可能(immutable)である必要があります。
例えば文字列、整数、タプルは使えますが、リストや辞書は使えません。
タプルは中身もハッシュ可能でなければなりません。
ok = {("x", 1): "point"} # タプルはキーにできる
try:
bad = {["x", 1]: "point"} # リストはキーにできない
except TypeError as e:
print(type(e).__name__, str(e))
TypeError unhashable type: 'list'
重複キーは上書きされる
同じキーを複数回指定すると、最後の値で上書きされます。
リテラル中の重複も最後が有効です。
d = {"a": 1, "a": 2}
print(d) # 最後の 2 が残る
{'a': 2}
挿入順序の保持と並び替え(sorted)
Python 3.7以降、辞書は挿入順序を保持します。
ただし、ある並べ替え基準で見たい場合はsorted()
とitems()
を使って並べ替えたリストを扱います。
scores = {"Bob": 78, "Alice": 92, "Charlie": 85}
# 追加した順序を保持
for name in scores:
print(name, scores[name])
print("--- sort by score desc ---")
# 値で降順ソートして表示
for name, score in sorted(scores.items(), key=lambda kv: kv[1], reverse=True):
print(name, score)
Bob 78
Alice 92
Charlie 85
--- sort by score desc ---
Alice 92
Charlie 85
Bob 78
よくあるエラー(KeyError)の回避
KeyErrorは存在しないキーを[]
で参照したときに発生します。
回避には次の方針が有効です。
- 任意キーの取得は
get(key, default)
を使う - 事前に
if key in d:
で確認する - 追加しながら使う場合は
setdefault()
で初期化する
config = {"retries": 3}
# 安全な読み取り
timeout = config.get("timeout", 5) # 無ければ 5
print(timeout)
# 必須なら確認してから使う
if "retries" in config:
print("retries:", config["retries"])
5
retries: 3
参考までに、ネストした辞書では段階的にget()
を使うと安全です。
例えばcfg.get("db", {}).get("host", "localhost")
のようにデフォルトの空辞書を渡します。
まとめ
辞書(dict)はキーと値のペアで素早く検索・更新できる強力なデータ構造です。
作成は{}
またはdict()
で簡単に行え、追加や更新はd[key] = value
、安全な取得はget()
、削除はpop()
やdel
を使います。
走査はitems()
でキーと値を同時に扱うと明快です。
結合はupdate()
か|
を状況に応じて選びます。
キーはハッシュ可能な型に限定され、重複キーは上書きされる点に注意してください。
必須なら[]、任意ならgetという基本と、inで存在確認を押さえれば、エラーを避けつつ読みやすいコードを書けます。
まずは小さな設定や検索テーブルから、辞書の扱いに慣れていきましょう。