辞書内包表記で辞書を作る

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

辞書内包表記で辞書を作る とは

辞書内包表記でキーと値のペアを 1 行で生成する方法を学びます。本レッスンでは、辞書内包表記で辞書を作る の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

辞書内包表記で辞書を作る

リストに リスト内包表記 があるのと同じように、辞書にも 辞書内包表記 があります。{key_expr: value_expr for item in iterable} という形で、for ループと [キー] = 値 の代入をワンライナーで書けます。前処理、変換、集計、ID 化など、Python で辞書を組み立てる場面はとても多いので、内包表記を使いこなせるとコードがぐっと短く読みやすくなります。

辞書内包表記の中心は キーと値の式{k: v for ... in ...} のうち、{}: が辞書だよ、と言っているサインです。

基本のかたち

一番シンプルな例として、リストから「要素 → 2 乗」の辞書を作ってみましょう。下記のとおりです。

Python

nums = [1, 2, 3, 4] squares = {n: n * n for n in nums} print(squares) # {1: 1, 2: 4, 3: 9, 4: 16}

{n: n * n for n in nums} の中で、n がキー、n * n が値。for n in nums のループで各要素を順番に処理し、{} に詰めていくイメージです。

if でフィルタリング

リスト内包表記と同じく、辞書内包表記でも if を末尾に付けて絞り込みできます。

Python

scores = {"alice": 90, "bob": 65, "carol": 82} passed = {name: s for name, s in scores.items() if s >= 80} print(passed) # {'alice': 90, 'carol': 82}

scores.items() でキーと値を同時に取り出し、if s >= 80 で条件を満たすものだけを新しい辞書にまとめる、という流れ。合格者だけ を抜き出すといった処理が 1 行で書けます。

キーと値を入れ替える

辞書を反転させる、よくある処理も内包表記で 1 行です。下記のとおりです。

Python

name_to_id = {"alice": 1, "bob": 2} id_to_name = {v: k for k, v in name_to_id.items()} print(id_to_name) # {1: 'alice', 2: 'bob'}

{v: k for k, v in d.items()} のリズムは典型例。値をキーに、キーを値に することで、逆引きテーブルが手軽に作れます。

動きを追ってみる

diagram (will load when visible)

概念図のとおり、for で 1 件取り出し、if で絞り込み、key: value を計算して新しい辞書に詰め込む、という流れ。「同じキーが複数回出てくる」場合は 最後の値が勝ち で上書きされる点に注意です。

よくある間違い

  1. {} を空セットと混同しない。{} は空辞書、set() で書くのが空セット。リテラル {1, 2} はセットになるので、辞書内包表記と区別しましょう。
  2. キーが重複した場合、KeyError にはならず 上書き されます。これは仕様。重複させたくないなら元データを先に検証しましょう。
  3. ジェネレータ式 (k: v for ...) という記法は存在しません。辞書には {...}、ジェネレータは (...) で別物です。

d = {x: x for x in nums} のように、キーと値が 同じ式 でも何の問題もない。テンプレ的な書き方も気軽にできるのが内包表記の魅力です。

リスト → 辞書への変換例

タプルのリストを辞書にしたい、というシチュエーションでも内包表記が活躍します。

Python

pairs = [("a", 1), ("b", 2), ("c", 3)] mapping = {k: v for k, v in pairs} print(mapping) # {'a': 1, 'b': 2, 'c': 3}

実は dict(pairs) でも同じ結果が得られますが、内包表記なら 値を加工 したり、if で絞れたり できるので応用が効きます。例えば {k: v * 10 for k, v in pairs} で値を 10 倍にした辞書を作れます。

内包表記は「中間データを作らずに一気に変形」できる構文。リスト内包と辞書内包をセットで覚えると、Python のデータ操作がぐっと速くなります。

enumerate との組み合わせ

要素に ID を付ける ようなテーブルを作るときは enumerate と組み合わせます。

Python

fruits = ["apple", "banana", "cherry"] indexed = {i: name for i, name in enumerate(fruits)} print(indexed) # {0: 'apple', 1: 'banana', 2: 'cherry'}

DB の id -> name テーブルを再現したい時、リストの順番を ID として扱いたい時など、シンプルながら頻出のパターンです。

やってみよう

単語のリスト words を受け取り、{単語: 文字数} の辞書を返す関数 word_length_dict を書いてみましょう。{w: len(w) for w in words} というたった一行の内包表記で書ければ完璧です。空リストでは空辞書を返すこと、これも内包表記なら自動で満たされます。

よくある質問

Q. 辞書の存在しないキーを参照するとどうなりますか?

A. d['missing'] は KeyError になります。安全に取り出すには d.get('missing', default) を使い、複雑な処理を書くなら collections.defaultdict を使うとキー初期化が省けます。in 演算子(if 'k' in d)で事前確認するのも定石です。

Q. 辞書のキーには何でも使えますか?

A. ハッシュ可能(イミュータブル)な値だけが使えます。文字列、数値、タプルは OK ですが、リストや辞書はキーにできません。タプルにすれば座標 (x, y) や複合キーとして使えるので、辞書を多重キーにしたいときに便利です。

Q. 辞書を for で回すと何が取れますか?

A. デフォルトはキーだけです。値も欲しい場合は d.values()、両方なら d.items() を使い for k, v in d.items(): と書きます。順序は Python 3.7 以降は挿入順が保証されているため、追加順に処理されます。

次のレッスン

次は sorted の key 引数でカスタムソート で、辞書内包表記でキーと値のペアを 1 行で生成する方法を学びます を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. 辞書内包表記 の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. 辞書内包表記 とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. 辞書内包表記 {key: value for x in iterable} を使う
  2. キーは単語、値は len(単語)
  3. 空リストでは空辞書を返す

入出力例

test-cases.txt

word_length_dict(["python","go","rust"]){"go":2,"python":6,"rust":4} word_length_dict(["hello"]){"hello":5} word_length_dict(["","a","ab"]){"":0,"a":1,"ab":2} word_length_dict([]){}

ヒント

main.py
main.py
学習モード

メモ

辞書内包表記で辞書を作る

⌘S で保存