この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: 辞書の作成
SEOタイトル: Python 辞書 (dict) 作成方法完全ガイド

この記事の要点
  • リテラル: {"key": "value"} が最も基本
  • コンストラクタ: dict(key="value") / dict([("a", 1)]) / dict(zip(keys, values))
  • 辞書内包表記: {k: v for k, v in pairs} で動的生成
  • マージ: {**a, **b} (3.5+) / a | b (3.9+) / a.update(b)
  • 派生型: defaultdict / OrderedDict / Counter / TypedDict

Python 辞書 (dict) とは

辞書 (dictionary, dict) は Python の組み込みコレクションの 1 つで、キー (key) と値 (value) のペアを格納するデータ構造です。ハッシュテーブルで実装されており、検索・挿入・削除が平均 O(1) です。

Python 3.7 以降は挿入順序が保持されることが公式に保証されています(CPython 3.6 から実装上は保持)。

1. 辞書リテラル {} で作る

# 基本
user = {"name": "Alice", "age": 30, "email": "alice@example.com"}

# 空の辞書
empty = {}

# ネスト
config = {
    "database": {
        "host": "localhost",
        "port": 5432,
    },
    "cache": {
        "ttl": 300,
    },
}

# キーは文字列以外も OK (ハッシュ可能なら何でも)
mixed = {
    1: "one",
    (1, 2): "tuple-key",
    "name": "Alice",
    True: "bool-key",   # 注: True == 1 なので 1: と衝突
}

2. dict() コンストラクタで作る

# キーワード引数 (キーは文字列のみ)
user = dict(name="Alice", age=30, email="alice@example.com")

# ペアのリスト / イテラブル
user = dict([("name", "Alice"), ("age", 30)])

# 既存辞書をコピー
copy = dict(original)

# 別の辞書 + 追加
extended = dict(original, extra=42)

# zip と組合せ
keys = ["name", "age", "email"]
values = ["Alice", 30, "alice@example.com"]
user = dict(zip(keys, values))

3. dict.fromkeys() で同じ値を持つ辞書

# 全部 0 で初期化
counts = dict.fromkeys(["a", "b", "c"], 0)
# {"a": 0, "b": 0, "c": 0}

# デフォルト値省略 → None
flags = dict.fromkeys(["x", "y", "z"])
# {"x": None, "y": None, "z": None}

# ⚠️ 落とし穴: 可変オブジェクトを共有してしまう
bad = dict.fromkeys(["a", "b"], [])
bad["a"].append(1)
print(bad)
# {"a": [1], "b": [1]}  ← 同じリスト!

# ✅ 修正: 内包表記で個別オブジェクト
good = {k: [] for k in ["a", "b"]}

4. 辞書内包表記

# 基本形
squares = {n: n * n for n in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# 既存リストから生成
words = ["apple", "banana", "cherry"]
length_map = {w: len(w) for w in words}
# {"apple": 5, "banana": 6, "cherry": 6}

# 条件付き
even_squares = {n: n * n for n in range(10) if n % 2 == 0}
# {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

# キーと値を入れ替え
original = {"a": 1, "b": 2, "c": 3}
swapped = {v: k for k, v in original.items()}
# {1: "a", 2: "b", 3: "c"}

# ネスト内包
matrix = {(i, j): i * 10 + j for i in range(3) for j in range(3)}

5. 辞書のマージ

a = {"x": 1, "y": 2}
b = {"y": 20, "z": 30}

# Python 3.5+ : アンパック展開
merged = {**a, **b}
# {"x": 1, "y": 20, "z": 30}  ← 後勝ち

# Python 3.9+ : | 演算子
merged = a | b
# {"x": 1, "y": 20, "z": 30}

# in-place マージ
a |= b
# a == {"x": 1, "y": 20, "z": 30}

# 旧来の方法
merged = a.copy()
merged.update(b)

# 衝突時に値をマージしたい場合
def deep_merge(a, b):
    result = a.copy()
    for k, v in b.items():
        if k in result and isinstance(result[k], dict) and isinstance(v, dict):
            result[k] = deep_merge(result[k], v)
        else:
            result[k] = v
    return result

6. collections の派生型

defaultdict: 自動初期化

from collections import defaultdict

# 値が無いキーアクセスで自動初期化
counts = defaultdict(int)
for word in ["apple", "banana", "apple", "cherry"]:
    counts[word] += 1
# defaultdict(int, {"apple": 2, "banana": 1, "cherry": 1})

groups = defaultdict(list)
for name, dept in [("Alice", "Eng"), ("Bob", "Sales"), ("Carol", "Eng")]:
    groups[dept].append(name)
# {"Eng": ["Alice", "Carol"], "Sales": ["Bob"]}

# defaultdict(set), defaultdict(dict) も同様

Counter: 要素数カウント

from collections import Counter

c = Counter("mississippi")
# Counter({"i": 4, "s": 4, "p": 2, "m": 1})

c.most_common(2)
# [("i", 4), ("s", 4)]

# 加算・減算もできる
c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)
c1 + c2  # Counter({"a": 4, "b": 3})
c1 - c2  # Counter({"a": 2})

OrderedDict: 明示的な順序保証

from collections import OrderedDict

# Python 3.7+ では通常の dict も順序保持
# OrderedDict 固有機能: move_to_end, popitem(last=False)
od = OrderedDict([("a", 1), ("b", 2), ("c", 3)])
od.move_to_end("a")
# OrderedDict([("b", 2), ("c", 3), ("a", 1)])

od.popitem(last=False)  # 先頭から取り出し
# ("b", 2)

ChainMap: 複数辞書を 1 つに見せる

from collections import ChainMap

defaults = {"theme": "light", "lang": "en"}
user_pref = {"theme": "dark"}

config = ChainMap(user_pref, defaults)
config["theme"]  # "dark"   (user_pref を先に見る)
config["lang"]   # "en"     (defaults から取得)

7. TypedDict (型ヒント付き辞書)

from typing import TypedDict, NotRequired

class User(TypedDict):
    name: str
    age: int
    email: NotRequired[str]   # Python 3.11+

def create_user(data: User) -> None:
    print(data["name"])

# 使用
create_user({"name": "Alice", "age": 30})
create_user({"name": "Bob", "age": 25, "email": "bob@example.com"})

# 静的型チェッカー (mypy / pyright) が型ミスを検出
# create_user({"name": "Charlie"})  # ← age 必須エラー

8. JSON との相互変換

import json

# dict → JSON 文字列
user = {"name": "Alice", "age": 30}
json_str = json.dumps(user, indent=2, ensure_ascii=False)

# JSON 文字列 → dict
data = json.loads(json_str)

# ファイル
with open("config.json") as f:
    config = json.load(f)

with open("output.json", "w", encoding="utf-8") as f:
    json.dump(config, f, indent=2, ensure_ascii=False)

# 日本語を含む場合は ensure_ascii=False

9. キーアクセスのパターン

user = {"name": "Alice", "age": 30}

# 基本アクセス(キーが無いと KeyError)
name = user["name"]

# get(): キーが無ければ None または指定値
age = user.get("age")          # 30
email = user.get("email")      # None
email = user.get("email", "")  # "" (デフォルト)

# setdefault(): キーが無ければ初期化して値返す
groups = {}
groups.setdefault("eng", []).append("Alice")
# {"eng": ["Alice"]}

# pop(): キー削除して値取得
age = user.pop("age")          # 30, user から削除
age = user.pop("age", None)    # None (キー無くてもエラーなし)

# in 演算子
if "name" in user:
    print(user["name"])

# items / keys / values
for k, v in user.items():
    print(f"{k} = {v}")

各作成方法の使い分け

場面推奨方法
固定キー・固定値リテラル {}
キーが Python 識別子のみdict(key=value)
キーと値のリストから生成dict(zip(keys, values))
すべて同じ初期値dict.fromkeys(keys, init) (immutable のみ)
動的生成辞書内包表記
自動初期化が欲しいdefaultdict
カウント用途Counter
API レスポンスの型保証TypedDict / dataclass

FAQ

Q: dict と OrderedDict の違いは?
A: Python 3.7+ では順序保持は両方同じ。OrderedDict は move_to_end, popitem(last=False), == が順序を考慮するなど追加機能あり。

Q: 辞書のキーに list は使えない?
A: 使えません。キーはハッシュ可能 (hashable)である必要があり、list / set / dict は不可。tuple や frozenset は OK。

Q: dict と dataclass、どちらを使うべき?
A: 構造が決まっているなら dataclass / TypedDict が型安全で IDE 補完も効く。動的なキーを扱うなら dict。

Q: 大量データの dict は効率的?
A: 平均 O(1) アクセスで高速ですが、メモリ消費は list より大きい。10 万件超なら専用 KVS(Redis 等)も検討。