辞書とセット
これまでの 2 つのレッスンでは、「位置による」アクセスを行うリストとタプルを学びました。しかし現実の生活では、「名前による」検索をすることがよくあります——単語で辞書を引く、名前で連絡先を探すなどです。辞書(dict) はこれを処理します。セットは数学的な集合演算のためのものです。どちらもデータ処理で非常に便利です。
1. 辞書とは
辞書は波括弧 {} で定義し、コロンで区切られたキーと値のペアのセットを含みます。
# 辞書を定義
student = {
"name": "Alice",
"age": 20,
"city": "Beijing"
}
print(student) # {'name': 'Alice', 'age': 20, 'city': 'Beijing'}
print(type(student)) # <class 'dict'>
基本的な CRUD 操作
# 辞書を作成
user = {}
# キーと値のペアを追加/変更
user["name"] = "Alice"
user["age"] = 25
print(user) # {'name': 'Alice', 'age': 25}
# 既存のキーを変更
user["age"] = 26
print(user) # {'name': 'Alice', 'age': 26}
# 値を読み取り
print(user["name"]) # Alice
# print(user["email"]) # KeyError! 存在しないキーはエラー
# get() で安全にアクセス — キーが存在しない場合のデフォルト値を指定
print(user.get("email")) # None — 見つからない、None を返す
print(user.get("email", "not set")) # not set — カスタムデフォルト値
# キーと値のペアを削除
del user["age"]
print(user) # {'name': 'Alice'}
dict["存在しないキー"] は KeyError を発生させます。これを避けるには get() を使います——None または指定したデフォルト値を返します。
例:学生情報管理(難易度 ⭐)
# 学生の完全な情報を辞書に保存
student = {
"name": "Bob",
"id": "2024001",
"scores": {"Chinese": 85, "Math": 92, "English": 78},
"is_active": True
}
# 基本情報を読み取り
print(f"Name: {student['name']}")
print(f"ID: {student['id']}")
# ネストした辞書から読み取り
math_score = student["scores"]["Math"]
print(f"Math score: {math_score}")
# get() で安全にアクセス
phone = student.get("phone", "not filled")
print(f"Phone: {phone}")
出力:
Name: Bob
ID: 2024001
Math score: 92
Phone: not filled
2. よく使われる辞書メソッド
すべてのキー、値、キーと値のペアを取得
user = {"name": "Alice", "age": 25, "city": "Beijing"}
print(user.keys()) # dict_keys(['name', 'age', 'city'])
print(user.values()) # dict_values(['Alice', 25, 'Beijing'])
print(user.items()) # dict_items([('name', 'Alice'), ('age', 25), ('city', 'Beijing')])
# 辞書を反復する最も一般的な方法
for key, value in user.items():
print(f"{key} = {value}")
出力:
name = Alice
age = 25
city = Beijing
pop() と setdefault()
# pop() — キーに対応する値を削除して返す
user = {"name": "Alice", "age": 25, "city": "Beijing"}
city = user.pop("city")
print(f"Removed city: {city}") # Removed city: Beijing
print(user) # {'name': 'Alice', 'age': 25}
# pop() にデフォルト値を指定でき、KeyError を回避
email = user.pop("email", "no email")
print(email) # no email — キーが存在しない、デフォルトを返す
# setdefault() — キーが存在すればその値を返し、存在しなければデフォルトを挿入
user = {"name": "Alice"}
result = user.setdefault("age", 18)
print(user) # {'name': 'Alice', 'age': 18}
# キーが既に存在する場合、setdefault は変更しない
result = user.setdefault("name", "Bob")
print(user) # {'name': 'Alice', 'age': 18} — 変更なし
update() — 辞書のマージ
# 2 つの辞書をマージ
defaults = {"theme": "light", "lang": "en", "font_size": 14}
custom = {"theme": "dark", "font_size": 16}
defaults.update(custom) # custom の値が defaults の一致するキーを上書き
print(defaults) # {'theme': 'dark', 'lang': 'en', 'font_size': 16}
例:単語カウント(難易度 ⭐⭐)
# 文中の単語出現回数をカウント
text = "apple banana apple orange banana apple"
word_count = {}
for word in text.split():
# 単語が既に辞書にある場合はインクリメント、なければ 1 に設定
word_count[word] = word_count.get(word, 0) + 1
print(word_count) # {'apple': 3, 'banana': 2, 'orange': 1}
# items() で出力
for word, count in word_count.items():
print(f"{word}: {count} times")
出力:
apple: 3 times
banana: 2 times
orange: 1 times
3. 辞書の反復とネスト
辞書を反復する 3 つの方法
user = {"name": "Alice", "age": 25, "city": "Beijing"}
# 方法 1:キーを反復
for key in user: # for key in user.keys(): と同等
print(f"{key}: {user[key]}")
# 方法 2:値を反復
for value in user.values():
print(value)
# 方法 3:キーと値のペアを反復(推奨)
for key, value in user.items():
print(f"{key} → {value}")
ネストした辞書
# ネストした辞書 — 複数の学生レコードを保存
students = {
"1001": {"name": "Alice", "scores": [85, 90, 78]},
"1002": {"name": "Bob", "scores": [92, 88, 95]},
"1003": {"name": "Charlie", "scores": [76, 85, 82]},
}
# ネストした辞書を反復
for sid, info in students.items():
name = info["name"]
avg = sum(info["scores"]) / len(info["scores"])
print(f"{sid} {name}: Average {avg:.1f}")
出力:
1001 Alice: Average 84.3
1002 Bob: Average 91.7
1003 Charlie: Average 81.0
4. セットとは
セットは波括弧 {} または set() で定義します。辞書のように見えますが、値がなくキーだけです。セットの特徴は:ユニークな要素、順序なし。
# セットを定義
fruits = {"apple", "banana", "orange", "apple"} # 重複は自動的に削除される
print(fruits) # {'orange', 'apple', 'banana'} — 順序は変わる可能性あり
# リストからセットを作成
numbers = set([1, 2, 2, 3, 3, 3])
print(numbers) # {1, 2, 3} — 重複が削除された
# 空のセットは set() を使用する。{} は空の辞書
empty_set = set()
print(type(empty_set)) # <class 'set'>
list(set(list_name)) で素早く重複を削除できます。ただし、セットは順序なしなので、元の順序は失われます。
セットの基本操作
# 追加と削除
s = set()
s.add("apple")
s.add("banana")
s.add("apple") # 重複追加は無効
print(s) # {'apple', 'banana'}
s.discard("apple") # 削除。存在しない場合もエラーにならない
print(s) # {'banana'}
# s.remove("non_existent") # KeyError が発生!
5. セット演算
ここでセットの真価が発揮されます——数学的な積集合、和集合、差集合:
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7, 8}
# 積集合 — 両方のセットに存在する要素
print(a & b) # {4, 5}
print(a.intersection(b)) # 同じ
# 和集合 — 両方のセットの全要素(重複なし)
print(a | b) # {1, 2, 3, 4, 5, 6, 7, 8}
print(a.union(b)) # 同じ
# 差集合 — a にあって b にない要素
print(a - b) # {1, 2, 3}
print(a.difference(b)) # 同じ
# 対称差 — a または b にあるが両方にはない要素
print(a ^ b) # {1, 2, 3, 6, 7, 8}
例:ユーザー権限分析(難易度 ⭐⭐⭐)
# ソーシャルプラットフォームのユーザー関係をシミュレート
all_users = {"Alice", "Bob", "Charlie", "Diana", "Eve"}
vip_users = {"Bob", "Diana", "Eve"}
blocked_users = {"Diana"}
# 「VIP ではない一般ユーザー」を見つける
normal_users = all_users - vip_users - blocked_users
print(f"Normal users: {normal_users}")
# 「アクティブな VIP(ブロックされていない)」を見つける
active_vip = vip_users - blocked_users
print(f"Active VIPs: {active_vip}")
# 「ブロックされたユーザーの中で VIP」を見つける
blocked_vip = vip_users & blocked_users
print(f"Blocked VIPs: {blocked_vip}")
# 「通知が必要なすべてのユーザー(VIP + ブロック)」を見つける
notify_users = vip_users | blocked_users
print(f"Users to notify: {notify_users}")
出力:
Normal users: {'Alice', 'Charlie'}
Active VIPs: {'Bob', 'Eve'}
Blocked VIPs: {'Diana'}
Users to notify: {'Bob', 'Diana', 'Eve'}
よくあるユースケース
- 設定管理:設定パラメータを保存(キー=設定名、値=設定値)。
get()でデフォルト値を使用 - 頻度カウント:辞書をカウンターとして使用——
dict[key] = dict.get(key, 0) + 1 - データグループ化:ネストした辞書
{"department": [employee_list]}で部門ごとにグループ化 - 重複除去:セットは自動的に重複を削除。
list(set(data))で素早く重複除去(順序は保持されない)。dict.fromkeys(data)で順序を保持した重複除去 - 権限チェック:セット演算で積集合(重複する権限)や差集合(不足している権限)を計算
❓ よくある質問
discard() と remove() の違いは何ですか?remove() は要素が存在しない場合に KeyError を発生させます。discard() は発生させません——存在すれば削除し、存在しなければ何もしません。要素が存在するかどうかわからない場合は、安全のために discard() を使いましょう。📖 まとめ
- 辞書は
{}を使用し、キーと値のペアを保存。キーで値を高速に検索 - 基本操作:
dict[key]で読み書き、get()で安全な読み取り、delで削除 - よく使われるメソッド:
keys()、values()、items()で反復。pop()で削除して返す。update()でマージ setdefault()は既存の値を返すか、デフォルトを挿入- 辞書の値は任意の型(リストや辞書も可)——ネスト構造が可能
- セットは
{}またはset()を使用。ユニークで順序なし。主に重複除去と数学演算に使用 - セット演算:
&積集合、|和集合、-差集合、^対称差
📝 練習問題
-
基本(難易度 ⭐):自分の個人情報(名前、年齢、都市、趣味)の辞書を作成してください。
get()で「job」フィールドを読み取り(なければ「not filled」を返す)。items()ですべてのキーと値のペアを出力してください。 -
中級(難易度 ⭐⭐):文
"hello world hello python world hello"が与えられたとき、各単語の出現回数をカウントし、最も頻繁に出現する単語を見つけてください。ヒント:辞書をカウントに使用。最大値を見つけるにはmax(dict.items(), key=lambda x: x[1])を使用。 -
挑戦(難易度 ⭐⭐⭐):「簡易連絡先管理プログラム」を書いてください。辞書(名前→電話番号)を使用します。以下をサポート:
add Alice 13800138000、del Alice、find Alice、all(すべて表示)。while Trueを使用し、exitで終了します。ヒント:コマンドの解析にsplit()を使用。



