目次
リストとジェネレータとリスト内包表記の違いのまとめ
書き方 | 評価方法 | 主な用途 | |
---|---|---|---|
リスト | [ ] | すぐに全要素生成 | 小~中規模データの操作 |
ジェネレータ | ( ) または 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] になります。
関連の記事