環境設定 数値 文字列 正規表現 リスト タプル 集合 辞書 ループ 関数 クラス データクラス 時間 パス ファイル スクレイピング その他

Pythonのリスト内包表記(list comprehension)をわかりやすく解説:二重for文とif elseの使い方

最終更新日 2019.11.30

Python のリスト内包表記(list comprehension)は for 文を含んだリストです。

a = [i + 1 for i in range(3)]

print(a)  # [1, 2, 3]

リストの要素は i + 1 で、irange(3) のイテレーターです。この例を見て、リスト内包表記を使って、文字列のリストから各文字数を要素とするリストを作ってください。

答えはこうなります。

x = ['Apple', 'Google', 'Microsoft']
a = [len(i) for i in x]

print(a)  # [5, 6, 9]

リスト内包表記の要素は「関数」です。これをリスト内包表記を使わずに書くと、下のように冗長なコードになります。

x = ['Apple', 'Google', 'Microsoft']
a = []
for i in x:
    a.append(len(i))

print(a)  # [5, 6, 9]

リスト内包表記で二重 for 文を使う

food = ['hamburger', 'potato']
size = ['s', 'm', 'l']

a = [f + ' ' + s for f in food for s in size]

print(a)
# ['hamburger s', 'hamburger m', 'hamburger l', 'potato s', 'potato m', 'potato l']

for を 2 回続けることができます。二重 for 文はリストのデカルト積を作るときに役立ちます。

リスト内包表記で if を使う

リスト内包表記は if 文も許可します。

a = [i * i for i in range(10) if i % 2 == 0]

print(a)
# [0, 4, 16, 36, 64]

for の後に if を置きます。次のコードは文法ミスです。

a = [i * i if i % 2 == 0 for i in range(10)]

# SyntaxError: invalid syntax

リスト内包表記で if else を使う

a = [i * i if i % 2 == 0 else i - 100 for i in range(10)]

print(a)
# [0, -99, 4, -97, 16, -95, 36, -93, 64, -91]

else も使うときは if else を前に置きます。

  • else を使わないときは後に置く
  • else を使うときは前に置く

別の例:

x = ['Apple', 'Google', 'Facebook', 'Microsoft']

a = [len(i) if len(i) % 2 == 0 else i for i in x]

print(a)
# ['Apple', 6, 8, 'Microsoft']

オライリーの Fluent Python (O'Reilly Media, Luciano Ramalho, p24) にあるように、リスト内包表記はできるだけ単純にするべきです。私は個人的に else を使うべきでないと考えています。map のような構文が好きな人は理解するかもしれませんが、そうでないプログラマーが上のコードを直感的に一瞬で理解するでしょうか。

Python はわかりやすいコードであるべきです。リスト内包表記やラムダ式は、少しでも複雑になると Python の求めるコードから逸脱します。それは他人のコードを楽に理解できるという Python の強みを損ねます。