タイトル: 値の参照
SEOタイトル: Python 辞書 (dict) の値参照 — d[key] / d.get() / setdefault / in / items()
| この記事の要点 |
|
基本: 角括弧アクセス
d = {"name": "Taro", "age": 25, "city": "Tokyo"}
# キーが存在 → 値が返る
print(d["name"]) # 'Taro'
# キーが無い → KeyError 例外
print(d["email"])
# Traceback (most recent call last):
# ...
# KeyError: 'email'
「絶対に存在する」と保証できる場面 (直前で代入した、入力スキーマで検証済み) では d["key"] がもっとも素直で速い書き方です。
get() でデフォルト付き参照
d = {"name": "Taro"}
# キー無し → None
print(d.get("email")) # None
# デフォルトを指定
print(d.get("email", "未設定")) # 未設定
# get() は元の dict を変更しない
print(d) # {'name': 'Taro'}
Web リクエストや JSON など キーの有無が不確定なデータ を扱うときの定番。例外を握りつぶさず、明示的にデフォルト値を意識させるのが Pythonic です。
setdefault() で初期化付き参照
# 「キーが無ければデフォルト値で初期化して返す」
d = {}
d.setdefault("count", 0) # 0
d["count"] += 1 # → {'count': 1}
# 集約処理での定番
words = ["apple", "banana", "apple", "cherry"]
counts = {}
for w in words:
counts.setdefault(w, 0)
counts[w] += 1
# counts == {'apple': 2, 'banana': 1, 'cherry': 1}
# 辞書のリスト化
groups = {}
for x in [1, 2, 3, 4, 5]:
key = "even" if x % 2 == 0 else "odd"
groups.setdefault(key, []).append(x)
# groups == {'odd': [1, 3, 5], 'even': [2, 4]}
defaultdict — もっと楽な setdefault
from collections import defaultdict
# キー未存在時に自動で int() = 0 を作る
counts = defaultdict(int)
for w in ["a", "b", "a", "c", "a"]:
counts[w] += 1
# defaultdict(, {'a': 3, 'b': 1, 'c': 1})
# キー未存在時にリストを作る
groups = defaultdict(list)
for k, v in [("odd", 1), ("even", 2), ("odd", 3)]:
groups[k].append(v)
# Counter — 出現回数集計の専用クラス
from collections import Counter
Counter(["a", "b", "a", "c", "a"])
# Counter({'a': 3, 'b': 1, 'c': 1})
Counter("mississippi").most_common(3)
# [('i', 4), ('s', 4), ('p', 2)]
in 演算子と KeyError 回避
d = {"name": "Taro", "age": 25}
# 存在チェック
if "name" in d:
print(d["name"])
# 否定
if "email" not in d:
print("メール無し")
# Python 2 では d.has_key("key") があったが、3 で廃止
# d.has_key("name") → AttributeError
items() / keys() / values() で反復
d = {"name": "Taro", "age": 25, "city": "Tokyo"}
# キーと値のペアで反復
for k, v in d.items():
print(f"{k} = {v}")
# name = Taro
# age = 25
# city = Tokyo
# キーだけ
for k in d.keys(): # for k in d: と同じ
...
# 値だけ
for v in d.values():
...
# items() はビュー — 元の dict が変わると追従する
view = d.items()
d["email"] = "taro@example.com"
list(view) # email も含まれる
Python 3.7 以降、dict は挿入順を保持します。items() も挿入順で返ります。
ネストした dict の値参照
data = {
"user": {
"name": "Taro",
"address": {"city": "Tokyo"}
}
}
# ❌ 途中のキーが無いと AttributeError / TypeError
city = data["user"]["address"]["city"]
# ✅ get() を連結 — どこかで None が返ったら止める
city = data.get("user", {}).get("address", {}).get("city")
# 安全だが冗長
# ✅ Python 3.13+ の Walrus 演算子と組み合わせ
if (user := data.get("user")) and (addr := user.get("address")):
city = addr.get("city")
# ✅ dpath / glom などのライブラリで安全アクセス
from glom import glom
city = glom(data, "user.address.city", default=None)
PHP の連想配列との比較
| 用途 | Python | PHP |
|---|---|---|
| キーで参照 | d["k"] (無いと KeyError) | $a["k"] (無いと Warning + null) |
| 安全参照 | d.get("k", default) | $a["k"] ?? default |
| 存在チェック | "k" in d | array_key_exists("k", $a) |
| キー反復 | for k in d | foreach ($a as $k => $v) |
FAQ
Q: d["key"] と d.get("key")、いつ使い分ける?
A: 存在を保証できるかで使い分けます。直前に d["key"] = ... したばかりなら角括弧、外部入力で不明なら get()。例外を握りつぶす目的で get() を使うのは避け、デフォルト値が業務的に意味を持つ場面で使ってください。
Q: setdefault と defaultdict、どちらが速い?
A: 大量のアクセスでは defaultdict が速いです。setdefault は呼ぶたびにデフォルト値を構築するためで、setdefault(k, []) のような重いデフォルトでは差が出ます。
Q: d.has_key("k") が AttributeError になる
A: Python 3 で廃止されました。"k" in d に置き換えてください。