3秒でわかる
先頭から順に要素を取り出せる決まりを備えたオブジェクト。リストも文字列も辞書もこの決まりを守るため、for 文が同じ書き方で回せます。
もう少し詳しく
どういうものか
イテラブルは、要素を 1 つずつ順に取り出す手続きを備えたオブジェクトを指す。日本語では反復可能オブジェクトと訳す。
言語ごとに決まりの名前は違うが、考え方は同じである。Python では __iter__() を持つオブジェクトがイテラブルで、iter() に渡すとイテレータが返る。JavaScript では Symbol.iterator を持つオブジェクトがこれにあたり、for...of や配列の展開構文が使える。
Python のリスト、タプル、文字列、辞書、集合、range、ファイルオブジェクトはすべてイテラブルである。
なぜ必要か
イテラブルという共通の決まりがあるおかげで、中身の構造を知らなくても同じ書き方で回せる。リストでも文字列でもファイルでも for x in ... の 1 行で済み、sum() max() sorted() のような関数も、相手がイテラブルでありさえすれば動く。
さらに、要素を全部メモリに載せる必要が無くなる。ファイルを 1 行ずつ読む処理は、10 GB のファイルでも数行分のメモリで回る。ジェネレータも同じ枠組みで、値を作りながら渡す。
具体例
# 標準の型はどれもイテラブル
for c in "abc":
print(c) # a b c
for key, value in {"a": 1, "b": 2}.items():
print(key, value)
# 自作クラスをイテラブルにする
class Countdown:
def __init__(self, start):
self.start = start
def __iter__(self):
n = self.start
while n > 0:
yield n
n -= 1
print(list(Countdown(3))) # [3, 2, 1]
print(sum(Countdown(3))) # 6 ── 標準の関数がそのまま使えるJavaScript でも同じ考え方になる。
const set = new Set([1, 2, 2, 3]);
for (const v of set) console.log(v); // 1 2 3
console.log([...set]); // [1, 2, 3]つまずきやすいところ
ジェネレータやファイルオブジェクトは 1 度回すと終端に達し、2 回目の for では何も出ない。リストは何度でも回せるので、この違いに気付かず「2 回目のループが空になる」と悩むことが多い。何度も使うなら list() で確定させる。
イテラブルとイテレータの区別も混乱しやすい。イテラブルは「回せるもの」、イテレータは「今どこまで進んだかを覚えている進行役」である。リストはイテラブルだがイテレータではないので、next() を直接渡すとエラーになる。
JavaScript では、波括弧で書く普通のオブジェクトはイテラブルではない点に注意する。for...of は使えず、Object.entries() を挟む。
似た用語との違い
| 語 | 何を指すか |
|---|---|
| イテラブル | 順に取り出せる決まりを持つオブジェクト |
| イテレータ | 現在位置を保持し、次の値を返すオブジェクト |
| ジェネレータ | yield で値を作りながら返すイテレータの一種 |
| シーケンス | 添字でも取り出せるイテラブル (リスト、文字列など) |