Documentation Python

Pythonで辞書(dict)に新しい項目を追加するには、複数の方法があります。この記事では、状況に応じた最適な方法を解説します。

辞書への項目追加方法の比較

方法用途元の辞書Python
dict[key] = value1項目追加変更される全バージョン
update()複数項目追加変更される全バージョン
setdefault()存在しない場合のみ追加変更される全バージョン
{**dict1, **dict2}辞書のマージ変更されない3.5+
dict1 | dict2辞書のマージ変更されない3.9+
dict1 |= dict2辞書のマージ(更新)変更される3.9+

キーと値を直接代入する方法

最もシンプルな方法は、キーと値を直接代入することです。

# 基本的な代入
my_dict = {'name': '田中', 'age': 25}
my_dict['email'] = 'tanaka@example.com'
print(my_dict)
# 出力: {'name': '田中', 'age': 25, 'email': 'tanaka@example.com'}

# 既存のキーに代入すると値が上書きされる
my_dict['age'] = 26
print(my_dict)
# 出力: {'name': '田中', 'age': 26, 'email': 'tanaka@example.com'}

変数をキーとして使う

user_data = {}

# 変数をキーとして使用
key = 'username'
value = 'tanaka123'
user_data[key] = value

# ループで複数追加
fields = [('name', '田中太郎'), ('age', 30), ('city', '東京')]
for k, v in fields:
    user_data[k] = v

print(user_data)
# 出力: {'username': 'tanaka123', 'name': '田中太郎', 'age': 30, 'city': '東京'}

update()メソッドを使う方法

update()を使うと、複数のキーと値を一度に追加できます。

my_dict = {'item1': 1, 'item2': 2}

# 辞書を渡す
my_dict.update({'item3': 3, 'item4': 4})
print(my_dict)
# 出力: {'item1': 1, 'item2': 2, 'item3': 3, 'item4': 4}

# キーワード引数で渡す
my_dict.update(item5=5, item6=6)
print(my_dict)
# 出力: {'item1': 1, 'item2': 2, 'item3': 3, 'item4': 4, 'item5': 5, 'item6': 6}

# タプルのリストで渡す
my_dict.update([('item7', 7), ('item8', 8)])
print(my_dict)

update()で既存の値を更新

config = {'debug': False, 'timeout': 30, 'retries': 3}

# 既存のキーがあれば上書き、なければ追加
config.update({'debug': True, 'max_connections': 100})
print(config)
# 出力: {'debug': True, 'timeout': 30, 'retries': 3, 'max_connections': 100}

setdefault()メソッド

setdefault()は、キーが存在しない場合のみ値を追加します。

# キーが存在しない場合:追加される
user = {'name': '田中'}
user.setdefault('age', 25)
print(user)  # {'name': '田中', 'age': 25}

# キーが存在する場合:何も変更されない
user.setdefault('name', '鈴木')
print(user)  # {'name': '田中', 'age': 25}(名前は変わらない)

setdefault()の実用例

# カテゴリ別にグループ化
items = [
    ('果物', 'りんご'),
    ('野菜', 'にんじん'),
    ('果物', 'バナナ'),
    ('野菜', 'キャベツ'),
]

categories = {}
for category, item in items:
    categories.setdefault(category, []).append(item)

print(categories)
# 出力: {'果物': ['りんご', 'バナナ'], '野菜': ['にんじん', 'キャベツ']}

Python 3.9+: マージ演算子 |

Python 3.9以降では、|演算子で辞書をマージできます。

# | 演算子(新しい辞書を作成)
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}

merged = dict1 | dict2
print(merged)  # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
print(dict1)   # {'a': 1, 'b': 2}(元の辞書は変更されない)

# |= 演算子(元の辞書を更新)
dict1 |= dict2
print(dict1)   # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

# キーが重複する場合は右側が優先
base = {'x': 1, 'y': 2}
override = {'y': 100, 'z': 3}
result = base | override
print(result)  # {'x': 1, 'y': 100, 'z': 3}

Python 3.5+: アンパック演算子 **

Python 3.5以降では、**でアンパックして新しい辞書を作成できます。

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

# 新しい辞書を作成(元は変更されない)
merged = {**dict1, **dict2}
print(merged)  # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

# 追加の値も同時に設定可能
result = {**dict1, 'e': 5, 'f': 6}
print(result)  # {'a': 1, 'b': 2, 'e': 5, 'f': 6}

実践例

設定のマージ

def load_config(user_config: dict = None) -> dict:
    """デフォルト設定とユーザー設定をマージ"""
    default_config = {
        'debug': False,
        'timeout': 30,
        'retries': 3,
        'log_level': 'INFO'
    }

    if user_config is None:
        return default_config

    # Python 3.9+
    return default_config | user_config

    # Python 3.5-3.8
    # return {**default_config, **user_config}

# 使用例
config = load_config({'debug': True, 'timeout': 60})
print(config)
# {'debug': True, 'timeout': 60, 'retries': 3, 'log_level': 'INFO'}

APIレスポンスの構築

def build_response(data: dict, status: str = 'success') -> dict:
    """APIレスポンスを構築"""
    base = {
        'status': status,
        'timestamp': '2024-10-23T10:00:00Z'
    }
    base['data'] = data
    return base

# 使用例
response = build_response({'user_id': 123, 'name': '田中'})
print(response)
# {'status': 'success', 'timestamp': '2024-10-23T10:00:00Z', 'data': {'user_id': 123, 'name': '田中'}}

辞書内包表記での追加

# 既存の辞書に変換を適用して新しい辞書を作成
prices = {'apple': 100, 'banana': 80, 'orange': 120}

# 税込み価格を追加
prices_with_tax = {
    **prices,
    **{f'{k}_with_tax': int(v * 1.1) for k, v in prices.items()}
}
print(prices_with_tax)
# {'apple': 100, 'banana': 80, 'orange': 120,
#  'apple_with_tax': 110, 'banana_with_tax': 88, 'orange_with_tax': 132}

パフォーマンスの比較

import timeit

# テスト用辞書
base = {f'key{i}': i for i in range(100)}
add = {f'new{i}': i for i in range(10)}

# 各方法の速度比較
def test_update():
    d = base.copy()
    d.update(add)
    return d

def test_unpack():
    return {**base, **add}

def test_merge_op():  # Python 3.9+
    return base | add

# 結果: update()とマージ演算子が最も高速
# アンパックは新しいオブジェクトを作成するため若干遅い

よくあるエラーと対処

# TypeError: unhashable type(ハッシュ不可の型をキーに使用)
my_dict = {}
# my_dict[[1, 2]] = 'value'  # エラー: リストはキーにできない

# タプルはキーにできる
my_dict[(1, 2)] = 'value'
print(my_dict)  # {(1, 2): 'value'}

まとめ

状況推奨方法
1項目追加dict[key] = value
複数項目追加dict.update({...})
存在しない場合のみ追加dict.setdefault(key, value)
辞書をマージ(新規作成)dict1 | dict2(3.9+)または {**dict1, **dict2}
辞書をマージ(更新)dict1 |= dict2(3.9+)または dict1.update(dict2)

目的に応じて適切な方法を選択することで、読みやすく効率的なコードを書くことができます。

参考文献

円