30
26

More than 3 years have passed since last update.

内包表記を極める

Last updated at Posted at 2019-12-04

内包表記とは

pythonでリストや辞書を作るときに使える記法。pythonはforループが遅いので、リストや辞書を作るときは内包表記を使うと段違いに高速化することができる。

基本

リストを作る場合はこんな感じ。

new_list = [f(myiter) for myiter in origin_list]

[ ]を{ }に替えると辞書も作れる。

new_dict = {indexes[myiter]:f(myiter) \
for myiter in origin_list}

基本的なパターンは下記になる。

[iteraterを使った表現 for (iterater) in 元となるiterableオブジェクト]

ifで条件分岐を使う

ifだけ場合

ifを1つだけ使う場合は最後につける。

10までの奇数を取り出す
odd = [i for i in range(10) if i%2 != 0]
# [1,3,5,7,9]

このときifはフィルタとしてはたらく。

if elseを使う場合

elseも使う場合はforの前につける。

奇数は"odd"、偶数は"even"を返す
xx = ["even" if i%2==0 else "odd" for i in range(10)]
# ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']

なぜifを前につけないといけないかというと、この時のifはさっきのifとは異なり、三項演算子の一部だからである。"even" if i%2 == 0 else "odd"で一つの表現になっていて、それがforで繰り返されることになる。

なおelseは複数使えない。複数の条件分岐をする場合、elifは使えない。if elseを複数使えば実現できる。

添え字が複数ある場合

一列に並べるパターン

xx = [i+j for i in i_list for j in j_list]

ネストするパターン

xx = [[i+j for i in range(3)] for j in range(5)]

numpyの操作を使いたかったらnp.arrayに渡す。

xx = np.array([[i+j for i in range(3)] for j in range(5)])

numpy.arrayはなかなか賢いので、2重、3重、4重でもちゃんと成型してくれる。

zipを使うパターン

(0,0),(1,1),(2,2),...と並べる。

xx = [i+j for i,j in zip(mylist_i,mylist_j)]

沼に突っ込まないために

ここまで来て、すでに「うっ」となるかもしれない。リスト内包表記は改行にルールがないので、1行が長くなり難読化してしまう。なので長くなる場合は必ず適切に改行を入れる

VSCodeの場合は1行目に\をいれれば、以降はいい感じに整形してくれる。実際は\を入れても入れなくても走る。

# ifを使う場合は絶対改行する
xx = ["even" if i % 2 == 0 else "odd" \
    for i in range(10)]

# 表現が長くなるなら、長くなる所で改行を入れる
zz = [np.sin(xx) + np.random.rand(xx.shape) \
    for xx in list_xx]
30
26
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
26