Skip to content

4.6 内包表記

内包表記(Comprehensions)は、ひとつ以上のイテレータからPythonデータ構造をコンパクトに作成できる形式です。 ループや条件テストを短い構文で結合でき、これが使いこなせるようになると、Python初心者レベルを卒業した証になります。

リスト内包表記を使えば、for ループと append() を使ってリストを構築する従来のコードを、1行でスッキリと書くことができます。

基本構文: [ expression for item in iterable ]

# 1から5までの整数のリストを作成する
number_list = [number for number in range(1, 6)]
print(number_list) # [1, 2, 3, 4, 5]
# 式に変更を加えることも可能
zero_to_four = [number - 1 for number in range(1, 6)]
print(zero_to_four) # [0, 1, 2, 3, 4]

後ろに if 条件を追加して、特定の要素だけを抽出することができます。

条件付き構文: [ expression for item in iterable if condition ]

# 1から5までのうち、奇数だけのリストを作成する
a_list = [number for number in range(1, 6) if number % 2 == 1]
print(a_list) # [1, 3, 5]

ループを入れ子にするのと同じように、内包表記でも for 節を複数使うことができます。

rows = range(1, 4)
cols = range(1, 3)
# (row, col) のタプルを持つリストを作成
cells = [(row, col) for row in rows for col in cols]
print(cells)
# [(1, 1), (1, 2), (2, 1), (2, 2), (3, 1), (3, 2)]

リストだけでなく、辞書(dict)にも内包表記があります。

基本構文: { key_item: value_item for item in iterable }

word = 'letters'
# 文字列の各文字をキー、その出現回数を値とする辞書を作成
# set(word) を使うことで、重複する文字の無駄な計算を省いています
letter_counts = {letter: word.count(letter) for letter in set(word)}
print(letter_counts)
# {'r': 1, 't': 2, 'e': 2, 's': 1, 'l': 1} (順序は実行環境によって異なります)

集合(set)も内包表記で作成できます。辞書内包表記に似ていますが、key: value のペアではなく、単一の値を記述します。

基本構文: { item for item in iterable }

# 1から5までのうち、3で割って1余る数値の集合を作成
a_set = {number for number in range(1, 6) if number % 3 == 1}
print(a_set) # {1, 4}

リスト内包表記の角かっこ [] を丸かっこ () に変えれば「タプル内包表記」になると思うかもしれませんが、実はタプルには内包表記がありません。 丸かっこを使うと、タプルではなくジェネレータオブジェクトが作成されます。

ジェネレータはイテレータにデータを供給する手段のひとつで、メモリ内にすべての値を一度に作成するのではなく、必要に応じて「一度にひとつずつその場で値を作り」ます。

# 丸かっこを使うとジェネレータ内包表記になる
number_thing = (number for number in range(1, 6))
print(type(number_thing)) # <class 'generator'>
# 直接forループで回すことができる
for number in number_thing:
print(number) # 1, 2, 3, 4, 5 が順番に出力される