Python講座 / リスト・辞書・集合の内包表記を使う

内包表記は、要素を変換したり条件に合うものを選んだりして、新しいコレクションを作る書き方です。短く読める変換に向き、複数の処理、例外対応、副作用がある場合は通常のfor文が分かりやすくなります。

変換式と絞り込み条件を分ける

リストの基本形は[expression for item in source if condition]です。末尾のifは要素を含めるかを判断します。一方、a if condition else bという式は、含める要素の値を選びます。置く場所によって役割が異なります。

外側に新しいリストを作っても、元の要素を複製したとは限りません。式が元の辞書やリストをそのまま使えば、そのオブジェクトは共有されます。新しい入れ物と、独立した入れ子データを区別してください。

変換結果の構造と反復順序は、for・range・enumerate・zipで繰り返すで扱う規則とつながります。

三種類のコレクションを作る

comprehensions.pyへ全体コードを保存し、仮想環境でpython comprehensions.pyを実行します。

amounts = [3500, -1, 8000, 0]
valid = [x for x in amounts if x >= 0]
labels = ["paid" if x > 0 else "free" for x in valid]
records = [("food", 3500), ("bus", 2500)]
by_name = {name: amount for name, amount in records}
remainders = {x % 3 for x in valid}
print(valid)
print(labels)
print(by_name)
print(sorted(remainders))

有効な金額、ラベル、名前をキーにした辞書、剰余の集合が出力されます。

[3500, 8000, 0]
['paid', 'paid', 'free']
{'food': 3500, 'bus': 2500}
[0, 2]

重複するキーや値の扱いを確認する

辞書内包表記で同じキーが繰り返されると、後の値が前を置き換えます。{category: amount for ...}を書くだけでは、カテゴリごとの合計にはなりません。集合内包表記は重複を取り除くので、結果の要素数が入力件数より少なくなる場合があります。

まず普通のfor文で規則を正しく表現し、単一の変換や絞り込みで読みやすくなるかを判断します。深い入れ子を一行へ押し込むと、行数が減っても修正や確認は難しくなります。集計には辞書で加算するループが適切な場合があります。

空結果と副作用を意識して試す

すべての要素が除かれると結果は空です。先頭要素を読んだり要素数で割ったりする前に、その状態の意味を決めます。表示やファイル保存だけを目的にリスト内包表記を使うと、使わないリストを作ることになるため、通常のfor文で副作用を明示します。

金額条件を>= 0から> 0に変えて0が消えることを確認します。同じ名前のレコードを追加して辞書の値が置き換わることを観察し、元へ戻してください。カテゴリ合計で必要なのは、キーを作ることだけでなく、同じキーへの累積です。

内包表記はforの順に要素を取り出し、ifを通った要素だけに結果式を適用します。[x * 2 for x in range(4) if x % 2 == 0] は0と2から [0, 4] を作ります。まずforとappendに展開して流れを確認し、例外処理や複数の副作用が必要なら通常のループを使います。

関連する公式リファレンス