Python リストとジェネレータとリスト内包表記の違い

目次

リストとジェネレータとリスト内包表記の違いのまとめ

書き方 評価方法 主な用途
リスト [ ] すぐに全要素生成 小~中規模データの操作
ジェネレータ ( ) または yield 必要な時に順次生成 大量データ・無限列
リスト内包表記 [ ] すぐに全要素生成 簡潔にリストを生成

リスト → データを全部メモリに置いておきたいとき。

ジェネレータ → データを順次処理したいとき(大量 or 無限)。

リスト内包表記 → リストを簡潔に作るための文法。単なる糖衣構文で、内部的には通常のリストと同じです。

糖衣構文

人間にとって書きやすく、読みやすくするための文法の工夫のことです。
中身は従来の書き方に展開できます。

リストとは

書き方: [ ]

特徴

すべての要素を一度に生成してメモリに保持。

ランダムアクセス(list[5] など)ができる。

複数回使える(再利用可能)。

リストの例

fruits = ["apple", "banana", "orange"]
fruits[0]        # "apple"
fruits.append("grape")  # 追加可能

ジェネレータとは

書き方: (式 for 変数 in イテラブル) または yield を使った関数

特徴

値が必要になった時に順次生成(遅延評価)。

メモリ効率が良い(大きなデータや無限列に向いている)。

使い切り(1度ループしたら空になる)。

インデックスアクセス不可(gen[2] はエラー)。

ジェネレータの例

gen = (x * x for x in range(5))

print(next(gen))  # 0
print(next(gen))  # 1
print(next(gen))  # 4
print(next(gen))  # 9
print(next(gen))  # 16
# print(next(gen))  # StopIteration エラー(もう要素がない)

[] ではなく () を使うことで「リスト」ではなく「ジェネレータ」を作ります。

x for x in range(5)
→ range(5)(0〜4)を順番に取り出して x に代入する。

x * x
→ 各 x に対して二乗を計算する。

()
→ 結果を即座にリスト化せず、その都度生成する(遅延評価)。

next() または for で順次にアクセスできます。

リスト内包表記とは

書き方: [式 for 変数 in イテラブル if 条件]

特徴

書きやすい短縮記法。

リストを返す(= すぐに全要素を生成する)。

「リストの生成」と「forループ+append」をまとめて書ける。

リスト内包表記の例

nums = [x * x for x in range(5)]
print(nums)   # [0, 1, 4, 9, 16]

上記は、以下のコードと同じ意味です。

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

range(5) → [0, 1, 2, 3, 4] なので
それぞれ二乗すると [0, 1, 4, 9, 16] になります。

関連の記事

Python リストとタプルとディクショナリの違い

△上に戻る