内包表記いろいろ

この記事は Python Tips Advent Calendar 2012 9日目の記事です。


まず、list, set, dict は、それらを生成するための専用の構文を持っています。

>>> [1,2,3] # リスト生成
[1, 2, 3]
>>> {1,2,3} # 集合生成
set([1, 2, 3])
>>> {1:1,2:2,3:3} # 辞書生成
{1: 1, 2: 2, 3: 3}


この構文を拡張した形で list, set, dict の内包表記が書けます。

>>> xs = [1,2,3]
>>> [x for x in xs] # リスト内包表記
[1, 2, 3]
>>> {x for x in xs} # 集合内包表記
set([1, 2, 3])
>>> {x:x for x in xs} # 辞書内包表記
{1: 1, 2: 2, 3: 3}


ただし、タプルだけは注意です。

>>> (1,2,3) # タプル生成
(1, 2, 3)
>>> (x for x in xs)  # ジェネレータ式 #doctest: +ELLIPSIS
<generator object <genexpr> at 0x...>

タプルの形式で内包表記を行うと、ジェネレータ式として扱われます。
タプルを内包表記で作りたいなら、

>>> tuple(x for x in xs) # タプル作るならこうする
(1, 2, 3)

このように書くのがいいでしょう。


また、内包表記はネストさせることができます。

>>> [(i,j) for i in range(3) for j in range(i)]
[(1, 0), (2, 0), (2, 1)]

これは以下のように書くのと大体同じです。

>>> for i in range(3):
...     for j in range(i):
...         print (i,j)
(1, 0)
(2, 0)
(2, 1)

当然これらは set や dict、ジェネレータでも使えます。

>>> {(i,j) for i in range(3) for j in range(i)}
set([(2, 0), (1, 0), (2, 1)])
>>> {i:j for i in range(3) for j in range(i)}
{1: 0, 2: 1}
>>> list((i,j) for i in range(3) for j in range(i))
[(1, 0), (2, 0), (2, 1)]


もちろん if と組み合わせることもできます。

>>> [(i, j) for i in range(5) if i%2 == 0 for j in range(i) if j%2 == 0]
[(2, 0), (4, 0), (4, 2)]


うまく活用していきましょう。そしてどこで改行するか悩みましょう。


.