🎯 目的
Pythonのdictは柔軟で便利ですが、その設計には暗黙の落とし穴や設計的な妥協があります。
本ガイドはそれを認識した上で、安全かつ明示的に辞書を使うための実践的ルールを提供します。
🧱 1. 原則:[] アクセスは「絶対にキーがある」と確信があるときだけ使う
# OK(キーが必ず存在するなら)
config = {"mode": "debug"}
mode = config["mode"]
# NG(キーがなければ例外)
mode = config["mode"] # ← KeyErrorの危険
📝 補足:[]は「失敗=例外」なので、失敗する可能性があるときは使わない。
🧩 2. キーが存在しない可能性があるなら .get() を使う
# OK
mode = config.get("mode", "release") # デフォルト付き
# OK(存在確認付き)
if (mode := config.get("mode")) is not None:
use_mode(mode)
else:
handle_missing_mode()
🔍 3. より厳密な構造を求めるなら TypedDict や dataclass を使う
from typing import TypedDict
class Config(TypedDict, total=False):
mode: str
debug: bool
def process(config: Config) -> None:
if "debug" in config:
do_debug(config["debug"])
✅ mypyなどで静的型チェックが可能
✅ 「存在しないかも」なキーを明示できる(total=False)
🧰 4. defaultdict は「ないときは初期値」で済ませたいときに有効
from collections import defaultdict
word_count = defaultdict(int)
word_count["apple"] += 1
- 👍 辞書にキーがなかった場合の初期化処理を省ける
- 👎 一見して「どのキーがもともと存在したか」が分かりづらくなる
🚨 5. try: ... except KeyError は最終手段
try:
value = config["setting"]
except KeyError:
handle_missing()
- ✅ 例外ベースのEAFPスタイル(「やってみてダメなら後処理」)
- 👎 濫用すると見通しが悪くなり、パフォーマンスも悪化
🧠 6. 静的解析を活用しよう(mypy / pylint / pyright)
-
TypedDictやdict[str, str]を明示することで、型チェックツールにキーの有無や型を検出させられる - 例:
--strictオプションで"Key may be missing"警告を得る
📋 7. よくある誤用と代替案
| 書き方 | 問題点 | 推奨 |
|---|---|---|
value = dict[key] |
キーがないと例外 |
dict.get(key) か if key in dict:
|
if dict[key] == "yes" |
KeyError or NoneTypeの比較になる |
if dict.get("key") == "yes" |
try: value = dict[key] |
冗長すぎる・多用NG |
get() or 明示的に存在確認 |
📦 おまけ:独自の safe_dict を使う方法(シンプルなラッパー)
class SafeDict(dict):
def safe_get(self, key, default=None):
return self[key] if key in self else default
config = SafeDict({"debug": True})
value = config.safe_get("port", 8080)
📖 まとめ:辞書を安全に使うための7つの心得
-
[]アクセスは「絶対にある」と確信ある場合だけ -
.get()を使って失敗を防ぐ - 明示的なデータ構造(TypedDict / dataclass)を使う
-
defaultdictで簡易的な初期化 -
try...exceptは限定的に使う - 静的解析を積極的に導入
- 誤用パターンを避け、明示性を保つ