Pythonの特徴の一つに内包表記があります。イテラブルなオブジェクトの各要素に対して処理をした結果をリスト・タプル・辞書化する際に内包表記は便利です。ここではリスト内包表記を中心にその使い方についてまとめていきます。
まずはよくある内包表記
>>> [x*x for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
内包表記とif文の組み合わせ
# 偶数のみを抜き取ってリスト化
>>> [x*x for x in range(10) if x%2==0]
[0, 4, 16, 36, 64]
zipを使って複数のオブジェクトに対して処理
>>> [x*y for x,y in zip(range(1,5), range(6,10))]
[6, 14, 24, 36]
独立した2つのリストオブジェクトに対して、組み合わせで処理をする
>>> even = [2, 4, 6]
>>> odd = [1, 3, 5]
>>> [e * o for e in even for o in odd]
[2, 6, 10, 4, 12, 20, 6, 18, 30]
これはfor文で書くと下記と同じ
>>> result = []
>>> for e in even:
>>> for o in odd:
>>> result.append(e*o)
>>> result
[2, 6, 10, 4, 12, 20, 6, 18, 30]
1次元配列同士の組み合わせから2次元配列を作る
>>> even = [2, 4, 6]
>>> odd = [1, 3, 5]
>>> [[e, o] for e in even for o in odd]
[[2, 1], [2, 3], [2, 5], [4, 1], [4, 3], [4, 5], [6, 1], [6, 3], [6, 5]]
if文の条件によって値を変える
>>> [data**2 if data%2==0 else data*2 for data in range(10) ]
[0, 2, 4, 6, 16, 10, 36, 14, 64, 18]
ネストの応用 1: 2次元配列を1次元配列に変換
>>> data = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]]
>>> [pix for row in data for pix in row]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
ネストの応用 1: 2次元配列の要素1つ1つに処理
>>> data = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]]
>>> [[pix * 2 for pix in row] for row in data]
[[2, 4, 6, 8], [10, 12, 14, 16], [18, 20, 22, 24], [26, 28, 30, 32]]
これはfor文で書くと下記と同じ
>>> data = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]]
>>> for i, row in enumerate(data):
>>> for j, pix in enumerate(row):
>>> data[i][j] *=2
[[2, 4, 6, 8], [10, 12, 14, 16], [18, 20, 22, 24], [26, 28, 30, 32]]
内包表記を用いて簡単な画像処理をしてみる
2次元配列で表現された画像に対して画像全体の平均を求める場合、下記で可能
>>> data = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]]
>>> data1 = [pix for row in data for pix in row]
>>> sum(data1) / len(data1)
8.5
2次元配列で表現された画像に対して標準偏差を求める場合、下記で可能
import math
data = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]]
data1 = [(pix - ave)**2 for row in data for pix in row]
var = sum(data1) / len(data1) ### 分散
std = math.sqrt(var) ### 標準偏差