Python辞書(dict)操作完全ガイド【初心者から上級者まで】

 

はじめに

Pythonの辞書(dict)は、キーと値のペアでデータを管理する最も重要なデータ構造の一つです。この記事では、基本的な操作から応用テクニックまで、辞書操作のすべてを網羅的に解説します。効率的なコードを書くための実践的なテクニックも紹介します。

辞書とは

辞書は、キー(key)と値(value)のペアを格納するミュータブル(変更可能)なデータ構造です。他の言語では「ハッシュマップ」や「連想配列」と呼ばれることもあります。

辞書の特徴

  • キーは一意: 同じキーは重複できません
  • 順序保持: Python 3.7以降、挿入順序が保持されます
  • 高速アクセス: O(1)の平均的な検索・挿入・削除時間
  • 柔軟性: 異なる型のキーと値を混在できます

基本的な辞書操作

辞書の作成

# 空の辞書
empty_dict = {}
empty_dict2 = dict()

# 初期値ありの辞書
person = {'name': '太郎', 'age': 30, 'city': '東京'}
scores = dict(math=90, english=85, science=92)

要素の追加・更新

person = {'name': '太郎'}
person['age'] = 30        # 新しいキーで追加
person['name'] = '花子'   # 既存キーの値を更新
person.update({'city': '大阪', 'job': 'エンジニア'})

要素の取得

person = {'name': '太郎', 'age': 30}
name = person['name']           # KeyErrorのリスク
age = person.get('age', 0)      # 安全な取得(デフォルト値付き)
job = person.get('job', '未設定') # 存在しないキーのデフォルト値

要素の削除

person = {'name': '太郎', 'age': 30, 'city': '東京'}
del person['city']              # キーと値を削除
age = person.pop('age', None)   # 削除と同時に値を取得
item = person.popitem()         # 最後の要素を削除して取得
person.clear()                  # 全要素を削除

辞書の反復処理

基本的な反復処理

scores = {'math': 90, 'english': 85, 'science': 92}

# キーのみ
for subject in scores:
    print(subject)

# キーと値
for subject, score in scores.items():
    print(f'{subject}: {score}')

# 値のみ
for score in scores.values():
    print(score)

リスト内包表記との組み合わせ

scores = {'math': 90, 'english': 85, 'science': 92}

# 80点以上の科目
high_scores = {k: v for k, v in scores.items() if v >= 90}

# すべての点数を10点加算
boosted = {k: v + 10 for k, v in scores.items()}

辞書の結合と更新

複数の辞書の結合

dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
dict3 = {'b': 20, 'e': 5}

# Python 3.9以降の結合演算子
merged = dict1 | dict2 | dict3

# updateメソッド
result = dict1.copy()
result.update(dict2, **dict3)

# 辞書展開
combined = {**dict1, **dict2, **dict3}

条件付き更新

config = {'debug': False, 'port': 8000}
user_config = {'debug': True, 'host': 'localhost'}

# 既存キーのみ更新
for key in config:
    if key in user_config:
        config[key] = user_config[key]

# setdefaultで安全な初期化
stats = {}
stats.setdefault('count', 0)
stats['count'] += 1

高度な辞書操作

defaultdictの活用

from collections import defaultdict

# リストのdefaultdict
groups = defaultdict(list)
for name, group in [('太郎', 'A'), ('花子', 'B'), ('次郎', 'A')]:
    groups[group].append(name)

# カウンターとしての活用
counter = defaultdict(int)
for char in 'hello world':
    counter[char] += 1

Counterクラスの使用

from collections import Counter

words = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']
word_count = Counter(words)

print(word_count.most_common(2))  # [('apple', 3), ('banana', 2)]
print(word_count['apple'])        # 3

辞書のソート

scores = {'math': 90, 'english': 85, 'science': 92, 'history': 88}

# キーでソート
sorted_by_key = dict(sorted(scores.items()))

# 値でソート(降順)
sorted_by_value = dict(sorted(scores.items(), key=lambda x: x[1], reverse=True))

# 複数条件でソート
students = [{'name': '太郎', 'score': 90}, {'name': '花子', 'score': 85}]
sorted_students = sorted(students, key=lambda x: (-x['score'], x['name']))

ネストした辞書の操作

深い辞書へのアクセス

data = {
    'users': {
        'user1': {'name': '太郎', 'profile': {'age': 30, 'city': '東京'}},
        'user2': {'name': '花子', 'profile': {'age': 25, 'city': '大阪'}}
    }
}

# 安全なネストアクセス
def deep_get(dictionary, *keys):
    for key in keys:
        if isinstance(dictionary, dict) and key in dictionary:
            dictionary = dictionary[key]
        else:
            return None
    return dictionary

age = deep_get(data, 'users', 'user1', 'profile', 'age')  # 30

辞書の平坦化

def flatten_dict(d, parent_key='', sep='_'):
    items = []
    for k, v in d.items():
        new_key = f"{parent_key}{sep}{k}" if parent_key else k
        if isinstance(v, dict):
            items.extend(flatten_dict(v, new_key, sep).items())
        else:
            items.append((new_key, v))
    return dict(items)

nested = {'a': 1, 'b': {'c': 2, 'd': {'e': 3}}}
flat = flatten_dict(nested)  # {'a': 1, 'b_c': 2, 'b_d_e': 3}

辞書を使ったデザインパターン

戦略パターン

def add(x, y): return x + y
def subtract(x, y): return x - y
def multiply(x, y): return x * y

operations = {
    'add': add,
    'subtract': subtract,
    'multiply': multiply
}

result = operations['add'](10, 5)  # 15

キャッシュ実装

cache = {}

def fibonacci(n):
    if n in cache:
        return cache[n]
    if n < 2:
        return n
    cache[n] = fibonacci(n-1) + fibonacci(n-2)
    return cache[n]

設定管理

DEFAULT_CONFIG = {
    'debug': False,
    'host': '127.0.0.1',
    'port': 8000,
    'timeout': 30
}

def get_config(user_config=None):
    config = DEFAULT_CONFIG.copy()
    if user_config:
        config.update(user_config)
    return config

パフォーマンス最適化

辞書のメモリ効率

# __slots__を使った軽量クラス
class Point:
    __slots__ = ['x', 'y']
    def __init__(self, x, y):
        self.x, self.y = x, y

# 大量データ処理での辞書作成
data = [('a', 1), ('b', 2), ('c', 3)]
# 高速
fast_dict = dict(data)
# より高速(キーが文字列の場合)
faster_dict = {k: v for k, v in data}

辞書の比較とマージ

dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = {'b': 20, 'c': 3, 'd': 4}

# 差分を見つける
diff_keys = dict1.keys() - dict2.keys()  # {'a'}
common_keys = dict1.keys() & dict2.keys()  # {'b', 'c'}

# 値が異なるキーを見つける
changed = {k: (dict1[k], dict2[k]) for k in common_keys if dict1[k] != dict2[k]}

JSON連携と辞書

JSONとの相互変換

import json

person = {'name': '太郎', 'age': 30, 'hobbies': ['読書', '映画']}

# 辞書からJSON文字列
json_str = json.dumps(person, ensure_ascii=False, indent=2)

# JSON文字列から辞書
parsed = json.loads(json_str)

# ファイルとの読み書き
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(person, f, ensure_ascii=False, indent=2)

with open('data.json', 'r', encoding='utf-8') as f:
    loaded = json.load(f)

エラーハンドリング

安全な辞書操作

def safe_dict_access(d, key, default=None):
    try:
        return d[key]
    except (KeyError, TypeError):
        return default

def safe_nested_access(d, *keys, default=None):
    try:
        for key in keys:
            d = d[key]
        return d
    except (KeyError, TypeError):
        return default

# 使用例
data = {'user': {'profile': {'name': '太郎'}}}
name = safe_nested_access(data, 'user', 'profile', 'name', default='不明')

実践的な辞書活用例

データ変換

# CSVライクなデータを辞書のリストに変換
raw_data = [
    ['名前', '年齢', '都市'],
    ['太郎', '30', '東京'],
    ['花子', '25', '大阪']
]

headers = raw_data[0]
records = [dict(zip(headers, row)) for row in raw_data[1:]]

グルーピング

from itertools import groupby

students = [
    {'name': '太郎', 'grade': 'A', 'subject': '数学'},
    {'name': '花子', 'grade': 'B', 'subject': '数学'},
    {'name': '次郎', 'grade': 'A', 'subject': '英語'}
]

# 成績別グルーピング
by_grade = {}
for student in students:
    grade = student['grade']
    by_grade.setdefault(grade, []).append(student)

よくある間違いと対策

可変オブジェクトをデフォルト値に使用

# 悪い例
def add_item(item, items={}):  # 危険!
    items[item] = True
    return items

# 良い例
def add_item(item, items=None):
    if items is None:
        items = {}
    items[item] = True
    return items

反復中の辞書変更

data = {'a': 1, 'b': 2, 'c': 3}

# 悪い例(RuntimeError発生の可能性)
# for key in data:
#     if data[key] > 1:
#         del data[key]

# 良い例
keys_to_delete = [k for k, v in data.items() if v > 1]
for key in keys_to_delete:
    del data[key]

まとめ

Python辞書は強力で柔軟なデータ構造であり、効率的なプログラムを書くために不可欠です。

重要なポイント

  • 基本操作の習得: get()、update()、items()などの安全な操作方法
  • 応用テクニック: defaultdict、Counter、辞書内包表記の活用
  • パフォーマンス: 適切な方法選択による処理速度向上
  • エラー対策: KeyErrorを避ける安全な実装
  • 実践応用: JSON連携、データ変換、グルーピングなどの実用技術

これらの技術を組み合わせることで、より読みやすく効率的なPythonコードが書けるようになります。辞書操作をマスターして、Pythonプログラミングのスキルを向上させましょう。

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座