3秒でわかる
リストや辞書を1行で組み立てるPythonの記法。繰り返しと絞り込みと変換をまとめて書け、3行のループよりも目的が伝わりやすくなります。
もう少し詳しく
どういうものか
内包表記は、既存のデータから新しいリストや辞書を組み立てる Python の書き方です。[式 for 変数 in 元データ if 条件] の形で、繰り返しと絞り込みと変換を 1 行にまとめます。リストのほかに、辞書内包表記、集合内包表記、そしてメモリを節約するジェネレータ式があります。
なぜ必要か
空のリストを作り、for でまわし、append する 3 行は、書くのが面倒なだけでなく読むときにも負担があります。3 行を最後まで読んで初めて「元のリストを加工しているだけ」と分かるからです。内包表記なら、行の先頭に「何を作るか」が書いてあるので、目的が 1 行目で伝わります。速度の面でも、append の呼び出しが省かれるぶん有利です。
具体例
prices = [1200, 480, 3000, 950]
# 3行で書く場合
result = []
for p in prices:
if p >= 1000:
result.append(p * 1.1)
# 内包表記
result = [p * 1.1 for p in prices if p >= 1000]
# 辞書内包表記
names = ["ito", "sato", "kudo"]
lengths = {n: len(n) for n in names}
# メモリを使わないジェネレータ式
total = sum(p * 1.1 for p in prices)つまずきやすいところ
if を書く位置で意味が変わります。末尾に置く if は絞り込みで、条件に合わない要素はリストに入りません。一方 [p if p > 0 else 0 for p in prices] のように前へ置く形は三項演算子で、全要素が残り値だけが変わります。この 2 つを取り違えて要素数が合わなくなる事故が多いところです。もうひとつは詰め込みすぎで、二重ループに条件が 2 つ付いた 1 行は、素直な for 文より確実に読みにくくなります。1 行が長くなってきたら普通のループへ戻す判断が要ります。
似た用語との違い
角かっこを丸かっこに変えるだけでジェネレータ式になり、巨大なデータでもメモリを使わずに済みます。ただし一度読み切ると空になるため、二度使う場合はリストにします。
覚え方
先頭に「作りたいもの」、真ん中に「どこから」、末尾に「どれを」。この順で読むと、長い内包表記でも意味を取り違えません。