言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Python辞典

  1. トップページ
  2. Python辞典
  3. 辞書.copy() / dict() / 辞書のマージ

辞書.copy() / dict() / 辞書のマージ

対応: Python 3.9(2020)

辞書のコピー・生成・マージを行う方法をまとめています。Python 3.9以降では『|』演算子を使ったシンプルなマージも利用できます。

構文

# 辞書をシャローコピー
新辞書 = 辞書.copy()

# キーワード引数や既存の辞書から新しい辞書を生成
新辞書 = dict(キー=値, ...)
新辞書 = dict(辞書)

# アンパック演算子で複数の辞書をマージ
マージ辞書 = {**辞書1, **辞書2}

# | 演算子でマージ(Python 3.9以降)
マージ辞書 = 辞書1 | 辞書2

関数・演算子一覧

関数・演算子概要
辞書.copy()辞書のシャローコピーを作成して返します。元の辞書を変更しても新しい辞書には影響しません(ただしネストした値は共有されます)。
dict(キー=値)キーワード引数から辞書を生成します。キーは文字列に限定されます。
dict(辞書)既存の辞書やイテラブルから新しい辞書を生成します。
{**辞書1, **辞書2}アンパック演算子を使って複数の辞書をマージした新しい辞書を生成します。キーが重複した場合は後者の値が優先されます。
辞書1 | 辞書22つの辞書をマージした新しい辞書を返します(Python 3.9以降)。キーが重複した場合は右側の値が優先されます。
辞書1 |= 辞書2辞書1に辞書2の内容をインプレースでマージします(Python 3.9以降)。

サンプルコード

dict_copy_merge.py
# copy() でシャローコピーを作成
original = {'name': '八神庵', 'age': 20}
copied = original.copy()
copied['name'] = '草薙京'
print(original['name']) # 『八神庵』と出力されます。元の辞書は変わりません。
print(copied['name']) # 『草薙京』と出力されます。

# dict() で辞書を生成
d1 = dict(name='テリー・ボガード', age=24)
print(d1) # 『{'name': 'テリー・ボガード', 'age': 24}』と出力されます。

# アンパック演算子でマージ
base = {'color': 'blue', 'size': 'M'}
extra = {'size': 'L', 'weight': 60}
merged = {**base, **extra}
print(merged) # 『{'color': 'blue', 'size': 'L', 'weight': 60}』と出力されます。

# | 演算子でマージ(Python 3.9以降)
d2 = {'x': 1, 'y': 2}
d3 = {'y': 99, 'z': 3}
result = d2 | d3
print(result) # 『{'x': 1, 'y': 99, 'z': 3}』と出力されます。

# |= でインプレースマージ
settings = {'theme': 'dark', 'lang': 'ja'}
overrides = {'lang': 'en', 'font': 'mono'}
settings |= overrides
print(settings) # 『{'theme': 'dark', 'lang': 'en', 'font': 'mono'}』と出力されます。

実行すると次のように出力されます。

python3 dict_copy_merge.py
八神庵
草薙京
{'name': 'テリー・ボガード', 'age': 24}
{'color': 'blue', 'size': 'L', 'weight': 60}
{'x': 1, 'y': 99, 'z': 3}
{'theme': 'dark', 'lang': 'en', 'font': 'mono'}

よくあるミス

よくあるミス1: 浅いコピーでネストしたデータが共有される

『dict.copy()』や『{**d}』は浅いコピー(shallow copy)です。値がリストや辞書などのミュータブルオブジェクトの場合、コピー先とコピー元で同じオブジェクトを参照します。

import copy

original = {
    '八神庵': {'power': 950, 'skills': ['闇払い', '八稚女']},
    '草薙京': {'power': 900, 'skills': ['百八式', '大蛇薙']},
}

# 浅いコピーはネストしたオブジェクトを共有する
shallow = original.copy()
shallow['八神庵']['power'] = 999 # オリジナルも変わってしまう
print(original['八神庵']['power']) # 999(意図しない変更)

次のように記述します。

# deepcopyで完全に独立したコピーを作る
deep = copy.deepcopy(original)
deep['八神庵']['power'] = 999
print(original['八神庵']['power']) # 950(変更されない)

よくあるミス2: |演算子はPython 3.9以降

辞書の『|』マージ演算子はPython 3.9以降で使えます。それ以前のバージョンでは使えません。

# Python 3.9以降のみ: | 演算子でマージ
team_a = {'八神庵': 950, '草薙京': 900}
team_b = {'テリー・ボガード': 880, 'ブルー・マリー': 820}
merged = team_a | team_b # Python 3.9以降

# Python 3.8以前でも動く方法
merged = {**team_a, **team_b}
# または
merged = dict(team_a)
merged.update(team_b)

概要

『辞書.copy()』はシャローコピーを作成します。辞書の値が文字列や数値などの不変オブジェクトであれば、コピー後に一方を変更してももう一方に影響しません。ただし値がリストや辞書などのミュータブルオブジェクトの場合は参照が共有されるため、深いコピーが必要なときは『copy.deepcopy()』を使います。

辞書のマージには複数の方法があります。『{**d1, **d2}』はPython 3.5以降で使え、3つ以上の辞書も一度にまとめられます。Python 3.9以降では『d1 | d2』という直感的な書き方が可能です。いずれの方法でもキーが重複した場合は後から指定した辞書の値が優先されます。意図せず値が上書きされないよう注意が必要です。

辞書内包表記による生成は『辞書内包表記』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。