この記事では、Pythonの辞書型(dict)の基礎から応用までを解説し、作成・追加・削除・検索・ソートやコピー方法、キーと値の扱い方、注意点を学べます。辞書操作でつまずくポイントも解消できます。
目次
Pythonの辞書型(dict)とは
辞書型の概要と特徴
Pythonの辞書型(dict)は、「キー」と「値」のペアでデータを管理するデータ構造です。英単語とその意味をセットで管理する辞書になぞらえて名付けられており、キーを使って値へ高速にアクセスできるというハッシュマップの特性を持っています。
辞書型には以下のような特徴があります。
- キーと値のペアでデータを保持
- キーはユニークでなければならない
- キーには不変(イミュータブル)な型(文字列、数値、タプルなど)が使用可能
- Python 3.7以降では挿入順序が保持される
- アクセス・追加・更新・削除が平均して高速(O(1)の計算量)
例えば、次のように社員IDと社員名を管理する用途で使えます。
employees = {
101: "Tanaka",
102: "Suzuki",
103: "Sato"
}
print(employees[102]) # 出力: Suzuki
辞書型が活躍するケース
Pythonの辞書型は、データの検索や紐付けが必要な場面で特に力を発揮します。キーによる高速アクセスが可能なため、次のような用途でよく活用されます。
- 設定情報の管理:アプリケーションの設定項目と値を対応付ける
- データベースやAPIから取得したデータの格納:JSON形式のデータとの相性が良い
- データのカテゴリ分け:カテゴリ名をキーに、属するデータを値として保持
- 高速なルックアップテーブル:条件分岐の代替として、キーで結果を直接参照
例えば、数値から曜日名を取得する辞書の例は以下の通りです。
weekdays = {
1: "Monday",
2: "Tuesday",
3: "Wednesday",
4: "Thursday",
5: "Friday"
}
print(weekdays.get(3)) # 出力: Wednesday
辞書型のメリットと制約
辞書型には数多くのメリットがありますが、一方で知っておくべき制約も存在します。
主なメリット
- 検索速度が速い:リスト型と比べ、キーによるアクセスは非常に高速
- 柔軟なデータ構造:値にリストや他の辞書を入れることも可能
- 順序保持(Python 3.7+):挿入順序を意識した処理が可能
主な制約
- キーは変更可能な型(リストや辞書)を使用できない
- 同じキーで新しい値を代入すると元の値は上書きされる
- メモリ使用量はリストなどに比べて大きくなる傾向がある
このように、Python辞書は柔軟かつ効率的なデータ管理が可能ですが、その特性を理解して適切に使うことが重要です。
辞書型の基本的な作り方
波括弧({})を使った作成方法
Pythonの辞書型(dict
)を最もシンプルに作成する方法は、波括弧({}
)を使う方法です。キーと値をコロン(:
)で区切り、要素同士はカンマで区切ります。可読性が高く、直感的に理解しやすいため、初心者から上級者まで幅広く利用されます。
person = {"name": "Alice", "age": 25, "city": "Tokyo"}
print(person)
# 出力: {'name': 'Alice', 'age': 25, 'city': 'Tokyo'}
空の辞書を作る場合は {}
と書くだけでOKです。
dict()コンストラクタでの作成方法
dict()
コンストラクタを使っても辞書を作れます。この方法では、キーを変数名のように記述し、値を代入する形になります。波括弧よりも可読性はやや劣りますが、引数に変数をそのまま指定できる点が便利です。
person = dict(name="Bob", age=30, city="Osaka")
print(person)
# 出力: {'name': 'Bob', 'age': 30, 'city': 'Osaka'}
ただし、dict()
に直接渡せるキーは、Pythonで有効な識別子(変数名として使える文字列)のみです。数字や空白を含むキーは波括弧構文を使う必要があります。
キーと値のリストやタプルから作成する方法
辞書は、キーと値のペアを格納したリストやタプルから作ることも可能です。主にlist
やtuple
の中に(キー, 値)
形式でデータを入れ、それをdict()
に渡します。
pairs = [("name", "Charlie"), ("age", 28), ("city", "Nagoya")]
person = dict(pairs)
print(person)
# 出力: {'name': 'Charlie', 'age': 28, 'city': 'Nagoya'}
この方法は、外部データや計算結果から動的に辞書を生成する場合によく使われます。
辞書内包表記で作成する方法
辞書内包表記は、リスト内包表記の辞書版で、簡潔に辞書を生成できます。ループや条件式を使って効率的に辞書を作成する際に便利です。
numbers = [1, 2, 3, 4]
square_dict = {n: n**2 for n in numbers}
print(square_dict)
# 出力: {1: 1, 2: 4, 3: 9, 4: 16}
この方法を使うと、大量のデータからルールに基づいた辞書を効率よく作成できます。
dict.fromkeys()による初期化
dict.fromkeys()
は、指定したキーの集合から同じ値を持つ辞書を作るクラスメソッドです。主に初期値を一括で設定する場合に有効です。
keys = ["name", "age", "city"]
person = dict.fromkeys(keys, None)
print(person)
# 出力: {'name': None, 'age': None, 'city': None}
注意: 初期値にミュータブル(変更可能)なオブジェクトを指定すると、全てのキーが同じオブジェクトを共有するため、意図しない挙動になる場合があります。その場合はcopy()
などを活用しましょう。
辞書の基本操作
値を取得する方法
キーを指定して取得([])
Pythonの辞書では、[]
を使ってキーを指定することで、対応する値を取得できます。この方法はシンプルで直感的ですが、指定したキーが存在しない場合にはKeyError
が発生する点に注意が必要です。
my_dict = {"apple": 100, "banana": 200}
print(my_dict["apple"]) # 100
# print(my_dict["orange"]) # KeyError が発生
キーが必ず存在することが分かっている場合や、エラー処理を別途記述する場合に有効な方法です。
get()メソッドで取得
get()
メソッドを使うと、キーが存在しない場合でもエラーを出さずに取得できます。存在しない場合はNone
、または指定したデフォルト値が返ります。
my_dict = {"apple": 100, "banana": 200}
print(my_dict.get("apple")) # 100
print(my_dict.get("orange")) # None
print(my_dict.get("orange", 0)) # 0 (デフォルト値を指定)
安全に値を取り出す必要があるケースや、キーが存在しない場合の代替値をその場で指定したい場合に便利な方法です。
要素を追加・更新する方法
[キー] = 値 での追加・更新
辞書に新しいキーと値を設定する場合も、既存のキーの値を更新する場合も、同じ構文dict[key] = value
を使います。
my_dict = {"apple": 100}
my_dict["banana"] = 200 # 新規追加
my_dict["apple"] = 150 # 値を更新
print(my_dict) # {'apple': 150, 'banana': 200}
setdefault()での追加
setdefault()
は、指定したキーが存在しない場合に新しいキーと値を追加し、その値を返します。すでにキーが存在する場合は既存の値を返し、更新は行いません。
my_dict = {"apple": 100}
my_dict.setdefault("banana", 200) # 追加される
my_dict.setdefault("apple", 150) # 更新されない
print(my_dict) # {'apple': 100, 'banana': 200}
update()での追加・更新
update()
は、複数のキーと値をまとめて追加・更新できるメソッドです。既存のキーは上書きされ、新しいキーは追加されます。
my_dict = {"apple": 100}
my_dict.update({"banana": 200, "apple": 150})
print(my_dict) # {'apple': 150, 'banana': 200}
要素を削除する方法
pop()で削除しつつ値を取得
pop()
は指定したキーの要素を削除し、その値を返します。キーが存在しない場合にデフォルト値を指定することも可能です。
my_dict = {"apple": 100, "banana": 200}
value = my_dict.pop("apple")
print(value) # 100
print(my_dict) # {'banana': 200}
popitem()でランダム削除
popitem()
は辞書から最後に追加された要素を削除し、そのキーと値のペアをタプルとして返します。(Python 3.7以降では挿入順に対応)
my_dict = {"apple": 100, "banana": 200}
item = my_dict.popitem()
print(item) # ('banana', 200)
print(my_dict) # {'apple': 100}
del文による削除
del
文を使うと、指定したキーと値を削除できます。キーが存在しない場合はKeyError
が発生します。
my_dict = {"apple": 100, "banana": 200}
del my_dict["banana"]
print(my_dict) # {'apple': 100}
clear()で全削除
clear()
は辞書内の全ての要素を削除し、空の辞書にします。
my_dict = {"apple": 100, "banana": 200}
my_dict.clear()
print(my_dict) # {}
要素の存在確認
in演算子でキーの存在を確認
in
演算子を使うと、辞書内に指定したキーが存在するか確認できます。存在すればTrue
、なければFalse
を返します。
my_dict = {"apple": 100, "banana": 200}
print("apple" in my_dict) # True
print("orange" in my_dict) # False
値の存在を確認
値が辞書内に存在するかを確認する場合は、values()
を用いて判定します。
my_dict = {"apple": 100, "banana": 200}
print(100 in my_dict.values()) # True
print(300 in my_dict.values()) # False
Pythonの辞書操作を正しく活用することで、データの検索や更新、削除を効率的に行うことができます。
辞書の反復処理と取り出し
keys()でキーを取得
Pythonの辞書型では、keys()
メソッドを使うことで、辞書に含まれるすべてのキーを取得できます。返り値はdict_keys
というビューオブジェクトであり、リストのように反復処理(イテレーション)が可能です。ビューオブジェクトは辞書の変更をリアルタイムに反映するため、動的なデータ参照にも向いています。
data = {"apple": 3, "banana": 5, "orange": 2}
# キー一覧を取得
print(data.keys()) # dict_keys(['apple', 'banana', 'orange'])
# for文でキーを順に処理
for key in data.keys():
print(key)
なお、list(data.keys())
とすればリストとして扱えるため、キーをソートしたり、インデックス指定で参照したりする場合に便利です。
values()で値を取得
辞書からすべての値を取り出したい場合は、values()
メソッドを使用します。こちらもdict_values
ビューオブジェクトを返し、辞書の値部分だけを反復処理できます。
data = {"apple": 3, "banana": 5, "orange": 2}
# 値一覧を取得
print(data.values()) # dict_values([3, 5, 2])
# 値の合計を計算
total = sum(data.values())
print(total)
値は重複する場合もあるため、重複を排除したい場合はset(data.values())
といった変換が有効です。
items()でキーと値のペアを取得
キーと値の両方を同時に取得したい時はitems()
メソッドを利用します。これにより、辞書内の要素を(キー, 値)
のタプルとしてまとめて取得でき、ペアごとの効率的な処理が可能になります。
data = {"apple": 3, "banana": 5, "orange": 2}
# キーと値のペアを表示
for key, value in data.items():
print(f"{key} は {value} 個あります")
items()
は特に、キーと値の両方に基づいて条件分岐を行いたい場合や、表形式のデータ出力などに役立ちます。
for文での辞書要素の反復処理
辞書はfor
文で直接反復処理すると、デフォルトではキーを順に取り出します。そのため、明示的にkeys()
を使わなくても、for key in dict_obj:
と書くことでキーの処理が可能です。
data = {"apple": 3, "banana": 5, "orange": 2}
# デフォルトでキーを反復
for key in data:
print(key, data[key])
# キーと値を同時に処理
for key, value in data.items():
if value >= 3:
print(f"{key} は在庫十分 ({value} 個)")
このようにPythonの辞書型は、柔軟な反復処理と取り出し方法を備えており、状況に応じてkeys()
・values()
・items()
を使い分けることで、効率的かつ可読性の高いコードを書くことができます。
辞書のソート
キーでソート
Pythonの辞書(dict
)は、デフォルトでは挿入順序を保持しますが、キー順に並び替える場合は明示的なソート処理が必要です。キーでソートすることで、データの検索や表示を見やすく整列でき、アルファベット順や数値の昇順など、順序の意味付けが可能になります。
キーでソートを行うには、sorted()
関数とdict.items()
を組み合わせて利用します。以下はキー昇順で並べ替える例です。
data = {"banana": 3, "apple": 5, "cherry": 2}
sorted_by_key = dict(sorted(data.items()))
print(sorted_by_key)
# {'apple': 5, 'banana': 3, 'cherry': 2}
もし降順でソートしたい場合は、sorted()
関数に引数reverse=True
を加えます。
sorted_by_key_desc = dict(sorted(data.items(), reverse=True))
print(sorted_by_key_desc)
# {'cherry': 2, 'banana': 3, 'apple': 5}
値でソート
辞書の値でソートしたい場合は、sorted()
関数のkey
パラメータに「値を基準にする」条件を渡します。これにより、例えば小さい値順に並べることができます。
data = {"banana": 3, "apple": 5, "cherry": 2}
sorted_by_value = dict(sorted(data.items(), key=lambda item: item[1]))
print(sorted_by_value)
# {'cherry': 2, 'banana': 3, 'apple': 5}
降順にする場合は、reverse=True
を併用します。
sorted_by_value_desc = dict(sorted(data.items(), key=lambda item: item[1], reverse=True))
print(sorted_by_value_desc)
# {'apple': 5, 'banana': 3, 'cherry': 2}
この方法は、ランキング表示やスコアの高い順に並べたい場合などで特に有効です。
キーと値のペアでソート
複雑な条件で辞書をソートしたい場合には、キーと値の両方を考慮したソートが可能です。例えば、まず「値」で降順に並べ、その後に「キー」で昇順に並べるといった複層的なソートが実現できます。
data = {"banana": 3, "apple": 5, "cherry": 5, "date": 2}
# 値を降順、値が同じ場合はキーで昇順
sorted_by_value_key = dict(sorted(data.items(), key=lambda item: (-item[1], item[0])))
print(sorted_by_value_key)
# {'apple': 5, 'cherry': 5, 'banana': 3, 'date': 2}
このように、lambda
関数でタプルを返す形にすれば、優先順位付きで複数のソート条件を組み合わせることができます。業務データの集計や成績順の判定など、複雑な並び替えが可能になるため、Python辞書の柔軟な活用が広がります。
辞書のコピーと複製
copy()メソッドでコピー
Pythonの辞書型(dict
)を複製する最も一般的な方法のひとつがcopy()
メソッドです。このメソッドを使うと、元の辞書と同じキーと値のペアを持つ新しい辞書オブジェクトが作成されます。作成されるのは浅いコピーであり、辞書内のネストされたオブジェクトまでは複製されず、参照が引き継がれます。
例えば以下のように利用します。
# 元の辞書
original = {"name": "Alice", "age": 25}
# コピーを作成
copied = original.copy()
print(copied) # {'name': 'Alice', 'age': 25}
copied
は新しい辞書オブジェクトなので、コピー後に要素を追加・削除しても元の辞書original
には影響しません。- ただし、値にリストや他の辞書が含まれている場合、その中身は共有されるため注意が必要です。
# ネストされたオブジェクトを持つ場合
original = {"user": {"name": "Alice"}}
shallow_copy = original.copy()
# 内部の辞書を書き換えると元の辞書にも反映される
shallow_copy["user"]["name"] = "Bob"
print(original) # {'user': {'name': 'Bob'}}
このように、ネスト構造を持つ辞書を完全に複製したい場合は、copy
モジュールのdeepcopy()
関数を使用するのが安全です。
dict.fromkeys()でキーのみコピー
辞書のキーだけをコピーし、値は特定の初期値で揃えたい場合には、dict.fromkeys()
メソッドが便利です。このメソッドは、指定したキーのリストやタプルから新しい辞書を生成します。
基本構文は次の通りです。
dict.fromkeys(キーのシーケンス, 既定値)
利用例は以下の通りです。
# 元の辞書
original = {"name": "Alice", "age": 25, "city": "Tokyo"}
# キーだけ抽出し、値をNoneで初期化
keys_only = dict.fromkeys(original.keys())
print(keys_only) # {'name': None, 'age': None, 'city': None}
# 値を特定の値で初期化
initialized = dict.fromkeys(original.keys(), 0)
print(initialized) # {'name': 0, 'age': 0, 'city': 0}
dict.fromkeys()
は元の辞書の順序を保持したまま新しい辞書を作ります(Python 3.7以降)。- 値として
list
やdict
などのミュータブルオブジェクトを指定すると、それが全キーで共有されるため、意図しない動作に注意が必要です。
# ミュータブルな値を設定した例
keys_only = dict.fromkeys(["a", "b"], [])
keys_only["a"].append(1)
print(keys_only) # {'a': [1], 'b': [1]} ← 両方のキーで共有
この特性を理解して使えば、dict.fromkeys()
はキー構造をベースにしたテンプレート辞書の初期化などに大変有効です。
辞書型を使う際の注意点
キーの重複と上書きに注意
Pythonの辞書型(dict
)では、各キーは一意である必要があります。同じキーを複数回指定して辞書を作成した場合、後から指定した値が前の値を上書きしてしまいます。意図せずデータを失う原因となるため、特に動的に辞書を構築する際は注意が必要です。
# キーの重複例
data = {"id": 1, "name": "Alice", "id": 2}
print(data) # {'id': 2, 'name': 'Alice'} と表示され、最初の'id':1は上書きされる
複数の値を紐付けたい場合は、値にリストやタプルを使う、またはdefaultdict
を利用するなどの代替手段を検討すると良いでしょう。
キーに使える型と使えない型
辞書のキーには、不変(immutable)な型しか使用できません。代表的な使用可能な型は次の通りです。
- 文字列 (
str
) - 数値 (
int
,float
,bool
) - タプル(ただし全要素が不変であること)
- None
一方、リストや辞書などのミュータブル(可変)な型はキーにできません。これは、辞書の内部でキーのハッシュ値が変化してしまうと正しく参照できなくなるためです。
# タプルはキーとして使える
valid_dict = { (1, 2): "tuple key"}
# リストをキーにするとエラーになる
invalid_dict = { [1, 2]: "list key"} # TypeError発生
この制約を理解しておくことで、安全かつ意図通りのデータ構造を構築できます。
辞書の順序の扱いについて
Python 3.7以降では、辞書は挿入順序を保持する仕様になりました。つまり、同じ辞書を反復処理すると、追加した順に要素が取り出されます。これはソート機能ではなく、あくまで「挿入順の保持」である点に注意が必要です。
data = {}
data["a"] = 1
data["b"] = 2
data["c"] = 3
print(data) # {'a': 1, 'b': 2, 'c': 3}
ただし、古いバージョンのPython(3.6以前)を使用している場合は、この順序保持は仕様として保証されていません。また、順序を厳密に制御したい場合や特別な並び替え処理が必要な場合は、collections.OrderedDict
の利用やソート処理を組み合わせると良いでしょう。
Python辞書でつまずきやすいポイント
キーと値の違いが分からない場合の対処
Pythonの辞書(dict
)は、「キーと値のペア」でデータを管理するデータ構造です。しかし、初心者の中にはキーと値の区別に戸惑う方が少なくありません。特にリストやタプルと異なり、辞書では順序ではなくキーによって値にアクセスするため、この概念を正しく理解することが重要です。
キー(key)は「データを探すためのラベル」で、値(value)は「キーに紐づく実際のデータ」です。例えば、英単語帳の見出し語がキー、その意味が値に相当します。
person = {"name": "Alice", "age": 30}
print(person["name"]) # Alice(キー"name"に対応する値)
このように、キーはユニーク(重複不可)であり、値はどんなデータでも設定可能です。キーと値を混同しないためのコツとしては、以下のような学習方法が有効です。
- 事例をもとに「~は誰?」や「~はいくつ?」という質問形式で辞書を操作する
- キーは必ず不変(文字列、数値、タプルなど)であることを意識する
- 「キー → 値」という対応表を紙や図で書き出す
この理解が深まると、Python辞書の操作が格段にスムーズになります。
1つのキーに複数の値が持てない理由
Pythonの辞書では、1つのキーに直接複数の値を割り当てることはできません。理由はキーがユニークであり、1つのキーに紐づく値は常に1つであるという仕様によります。もし同じキーで再度値を設定すると、以前の値は上書きされ、最後に代入した値だけが残ります。
fruit = {"apple": "red"}
fruit["apple"] = "green"
print(fruit) # {'apple': 'green'}("red"は上書きされ消える)
では、1つのキーに複数の値を関連付けたい場合はどうすればよいでしょうか。その場合は、値としてリストやタプルなどのコレクション型を使うのが一般的です。
fruit_colors = {"apple": ["red", "green"]}
print(fruit_colors["apple"]) # ['red', 'green']
この方法を使えば、キーの一意性を保ちながらも複数の値を扱うことができます。特にデータ集計やタグ付けといった場面で有効なパターンです。
まとめると、「辞書のキーは常に一意」という仕様を前提に、複数値が必要な場面ではリストや辞書のネストといった工夫を取り入れることが、Python辞書を柔軟に活用するコツです。
辞書の応用的な活用例
ネストされた辞書の利用
Pythonの辞書型では、値としてさらに辞書を格納することで、ネストされた辞書を作成できます。これにより階層構造を持つデータを直感的に扱うことができ、JSON形式に近いデータ構造の表現にも適しています。たとえば、ユーザー情報のように複数の属性をまとめる場合に便利です。
user_data = {
"user1": {
"name": "Alice",
"age": 28,
"skills": ["Python", "Django"]
},
"user2": {
"name": "Bob",
"age": 35,
"skills": ["JavaScript", "React"]
}
}
# ネストされた値へのアクセス
print(user_data["user1"]["skills"][0]) # 出力: Python
ネストされた辞書を使用する際は、階層が深くなりすぎると可読性が落ちるため、適切な深さに抑えるのがポイントです。また、欠損キーを安全に取り扱うためには、dict.get()
やcollections.defaultdict
の併用が有効です。
辞書のマージ(結合)方法
複数の辞書をまとめて1つの辞書に統合する操作は、データ統合や設定値の上書き適用など様々な場面で役立ちます。Python 3.5以降では、**
アンパック演算子を使って簡潔にマージできます。Python 3.9以降では、|
演算子や|=
演算子も利用可能です。
# サンプル辞書
dict_a = {"x": 1, "y": 2}
dict_b = {"y": 3, "z": 4}
# アンパックによるマージ
merged = {**dict_a, **dict_b}
print(merged) # 出力: {'x': 1, 'y': 3, 'z': 4}
# Python 3.9以降の | 演算子
merged_alt = dict_a | dict_b
print(merged_alt) # 出力: {'x': 1, 'y': 3, 'z': 4}
キーが重複する場合、後から指定した辞書の値で上書きされる点に注意してください。また、複雑なマージ(配列の結合やネストされた辞書の統合)には再帰的な処理が必要になるケースもあります。
集計やカウント処理への活用
辞書はデータの頻度集計やカテゴリー別の集計処理にも適しています。特にcollections.Counter
クラスを使えば、要素の出現回数を簡単にカウントできます。これによりログ分析、ワードカウント、アクセスランキング作成など様々な用途に応用可能です。
from collections import Counter
# 単語の出現回数をカウント
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
count = Counter(words)
print(count) # 出力: Counter({'apple': 3, 'banana': 2, 'orange': 1})
# 辞書としてアクセス可能
print(count["apple"]) # 3
また、自前で集計を行う場合には、dict.get()
を用いて存在しないキーに初期値を設定すると便利です。
data = ["A", "B", "A", "C", "B", "A"]
counter = {}
for item in data:
counter[item] = counter.get(item, 0) + 1
print(counter) # 出力: {'A': 3, 'B': 2, 'C': 1}
このように、Python辞書は単なるキーと値のマッピング以上に、集計やデータ解析においても強力な役割を果たします。