Pythonの内包表記について

Pythonでは、内包表現という便利な記法があり、これを使うとlistの初期化などを簡潔に書くことができます。

list内包表記

次のような記法を内包表記と言います。

x = [i*2 for i in range(5)]
print(x)
# [0, 2, 4, 6, 8]

x = [i*2 for i in range(5) if i%2 == 0]
print(x)
# [0, 4, 8]

listを生成する内包表記は、[x for y in z]と書きます。zにはiterableがきます。iterableとは、list、str、rangeオブジェクトなどです。yはループ変数で、zから一つずつ値を取り出してこのyに代入されます。そのときのxの部分の値をリストにappendしていくという動作になっています。

xの部分が評価されるのは、値をひとつyに取り出したあとです。つまり、内包表記と等価なコードは以下のようになります。

w = [x for y in z]

// ↓これと等価
w = []
for y in z:
  w.append(x)


x = [i*2 for i in range(5)]

// ↓これと等価

x = []
for i in range(5):
  x.append(i*2)


x = [i*2 for i in range(5) if i%2 == 0]

// ↓これと等価

x = []
for i in range(5):
  if i%2 == 0:
    x.append(i*2)

set内包表記

setに対しても同様に内包表記が使えます。

x = {x*2 % 5 for x in range(4)}
print(x)
# {0, 1, 2, 4}

dict内包表記

dictに対しても同様に内包表記が使えます。

x = {i*2:j for i,j in zip(range(4),range(4))}
print(x)
# {0: 0, 2: 1, 4: 2, 6: 3}
# dict内包表記は、{i:j for ... }のように":"を使う。またzip()と相性が良い。

tuple内包表記

tupleに対して内包表記は使えません。( ) のなかに内包表記の書式で書くとこれはgenerator式とみなされます。

x = (i for i in range(5))

print(type(x))
# <class 'generator'>

print(x)
# <generator object <genexpr> at 0x000001B284FD25E8>

for i in x:
    print(i)
# 0
# 1
# 2
# 3
# 4

ただし、generator式なので、tupleのコンストラクタに渡して直接的にtuple化することができます。

x = tuple(i for i in range(5))
print(x)
# (0, 1, 2, 3, 4)

内包表記のなかでforの連結

内包表記のなかで次のようにforを2つ使った場合、左側のforから実行されているように見えます。最後にリストに追加していくものが、先頭にきます。

x = [[1,2,3],[4,5],[6]]
y = [inner for outer in x for inner in outer]
print(y)
# [1, 2, 3, 4, 5, 6]

これは、インデントするのであれば、次のようになります。

y =
[
inner
for outer in x
  for inner in outer
]

内包表記のなかでlistのネスト

次のように内包表記のなかでリストをネスト(入れ子)にした場合、後ろ側のforが先に実行されているように見えます。

x = [ [(i,j) for i in range(3)] for j in range(3)]
print(x)
# [[(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)]]

これは、インデントするのであれば、次のようになります。

x = 
[
  [
  (i,j)
  for i in range(3)
  ]
  for j in range(3)
]

(Visited 26 times, 1 visits today)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です