Python入門:iterable (イテラブル) って何? forループの仕組みを徹底解説!
こんにちは。ゆうせいです。
新人エンジニアの皆さん、Pythonでのプログラミング、楽しんでいますか?
きっと、リストや文字列を扱うときに for ループをたくさん使っていることでしょう。
my_list = [1, 2, 3]
for item in my_list:
print(item)
こんな風に書くと、リストの中身が順番に出てきて便利ですよね。
でも、なぜ for ループはリストや文字列では使えるのに、例えばただの数値(整数)では使えないのか、不思議に思ったことはありませんか?
その秘密の鍵を握っているのが、今回解説する「iterable(イテラブル)」という概念なんです。
この仕組みを知れば、Pythonの「繰り返し処理」への理解がグッと深まりますよ!
iterable (イテラブル) とは?
すごく簡単に言ってしまうと、iterableとは「forループで順番に中身を取り出せるモノ」のことです。
「反復可能」なんて訳されたりもしますね。
皆さんがよく使う、これらは全部iterableです。
- リスト (
[1, 2, 3]) - タプル (
(1, 2, 3)) - 文字列 (
"hello") - 辞書 (
{"a": 1, "b": 2}) (キーを順番に取り出せます) - セット (
{1, 2, 3})
これらはすべて、「中身を一つずつ順番に取り出す」という共通の能力を持っています。
for ループは、この「能力を持っているモノ」しか受け付けてくれないんです。
例え話:ペッツ(PEZ)のお菓子
懐かしいお菓子の「森永ペッツ」を想像してみてください。
キャラクターの頭がついたケース(ディスペンサー)に、ブロック状のお菓子(リフィル)が詰まっていますよね。
あのケースが「iterable」です。
ケースは「お菓子を順番に取り出せる」という能力を持っています。
for ループは「ペッツのケース(iterable)をくれ!そしたら中身を一個ずつ出してあげるよ」と待っているイメージです。
iterableの相棒、「iterator (イテレータ)」
さて、「ケースがiterable」なのは分かりました。
では、for ループが始まると、Pythonの内部では何が起きているのでしょう?
ここで登場するのが「iterator(イテレータ)」という相棒です。
- iterable (イテラブル): ペッツのケース本体。データの「入れ物」。
- iterator (イテレータ): お菓子を一個ずつカシャンと押し出す「仕組み」そのもの。
for ループが始まると、まずPythonはiterable(ケース)に「君専用のイテレータ(押し出す仕組み)をちょうだい!」とお願いします。
(専門用語で言うと、__iter__() メソッドが呼ばれます)
iterableは「はい、どうぞ」と、自分専用のiteratorを新しく作って渡します。
for ループは、その渡されたiteratorに対して「次のお菓子ちょうだい!」とお願いします。
(専門用語で言うと、__next__() メソッドが呼ばれます)
iteratorは「はい、どうぞ」と一個お菓子(データ)を渡します。iteratorは「次はここからだな」と、自分の位置を覚えています。
for ループは、iteratorからお菓子がなくなるまで「次ちょうだい!」と聞き続けます。
そして、ついにiteratorが「もう空っぽだよ!」(StopIteration例外)と伝えると、for ループは「了解!仕事おわり!」となって終了します。
これが for ループの裏側で起きていることの全体像です。
iterableとiteratorの違い:重要な注意点
「なんだか似ててややこしい!」と思いますよね。
ここが一番大事なポイントなので、しっかり押さえてください。
- iterable (ケース) は、何回でも使えます。
- iterator (押し出す仕組み) は、基本「一回使い切り」です。
どういうことでしょう?
ペッツのケース(iterable)は、中身が空になっても、また新しいお菓子(データ)を詰めれば何回でも使えますよね。
for ループでリストを何回も回せるのは、for ループが始まるたびに、リスト(iterable)が「新品のiterator」を渡してくれるからです。
しかし、iterator(押し出す仕組み)自体は、一度「空っぽだよ!」と言ったら、もうお菓子をくれません。
一度最後まで進んだら、そのiteratorは役目を終えてしまうんです。
やってしまいがちなミス
この「iteratorは使い切り」という性質を知らないと、こんなミスをすることがあります。
my_list = [1, 2, 3]
# iter()関数で、手動でiteratorを作ってみます
my_iterator = iter(my_list)
print("1回目のループ")
for item in my_iterator:
print(item)
# 出力:
# 1回目のループ
# 1
# 2
# 3
print("2回目のループ")
# さっき使い切ったiteratorを、もう一度使おうとすると…
for item in my_iterator:
print(item)
# 出力:
# 2回目のループ
# (何も表示されない!)
2回目のループでは何も表示されません!
なぜなら、my_iterator という「押し出す仕組み」は、1回目のループで既に最後まで進んで「空っぽ」になってしまったからです。
もし2回目もループさせたいなら、もう一度リスト(iterable)にお願いして、
my_iterator2 = iter(my_list)
というように、「新品のiterator」をもらう必要があるんです。
普段 for item in my_list: と書いている時は、Pythonが自動で毎回新品のiteratorを作ってくれているので、私たちが意識する必要がないだけなんですね。
なぜこんな面倒な仕組みが? (メリット)
「全部iterableだけでやればいいのに、なぜiteratorなんて分けるの?」
そう思うかもしれません。
この仕組みには、大きなメリットが2つあります。
1. 統一的な操作ができる
Pythonにはリスト、文字列、辞書、ファイルなど、いろんな「入れ物」があります。
for ループは、相手がどんな形の「入れ物」でも気にしません。
ただ「iteratorをちょうだい」とお願いして、「次ちょうだい」と聞くだけです。
このおかげで、私たちはどんなiterableなモノでも、同じ for ループという文法で扱えるわけです。これはとても便利!
2. メモリに優しい (超重要)
これが最大のメリットです。
もし、10億件のデータが記録された巨大なログファイルがあると想像してください。
iterableな仕組みがなかったら、for ループで処理するために、まず10億件のデータを「全部」メモリに読み込まないといけません。
パソコンのメモリが足りなくて、パンクしてしまいますよね。
でもiteratorの仕組みなら大丈夫。
iteratorは「次ちょうだい」と言われたときに、「一個だけ」データをファイルから読み込んで渡します。
10億件のデータを一度にメモリに置くのではなく、必要な分(一個)だけをその都度用意するんです。
おかげで、どれだけ巨大なデータでも、少ないメモリで効率よく処理できる!
これは、Pythonがデータ分析やWebサーバーなど、大きなデータを扱う分野で活躍できる大きな理由の一つです。
まとめと次のステップ
お疲れ様でした!
iterableとiteratorの関係、なんとなく掴めたでしょうか?
- iterable (イテラブル):
forループで回せる資格を持つモノ(リストや文字列など)。 - iterator (イテレータ): iterableから作られる、一個ずつデータを取り出す「使い切りの道具」。
for ループは、iterableからiteratorを作ってもらい、iteratorが空になるまでデータを取り出す、という仕組みで動いています。
この仕組みを理解できたら、あなたはもう初心者卒業です!
次に学ぶステップとしては、以下の二つがおすすめです。
- ジェネレータ (Generator)yield というキーワードを使って、この「iterator」をとても簡単に自作できる仕組みです。メモリ効率の良いプログラムを作るために必須の知識ですよ。
- リスト内包表記 (List Comprehension)iterableなモノから、新しいリストを簡潔に作るためのカッコいい書き方です。new_list = [x * 2 for x in my_list] のような書き方を見たことがありませんか?
Pythonは奥が深いですが、こうした「裏側の仕組み」を知ると、コードの書き方が変わり、エラーの解決も早くなります。
ぜひ、怖がらずに色々なiterableを for ループで回してみてくださいね!応援しています。
セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク
投稿者プロフィール
- 代表取締役
-
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。
最新の投稿
山崎講師2025年10月26日Pythonのimport完全ガイド!パッケージとモジュールの階層構造をスッキリ理解しよう
山崎講師2025年10月26日Python関数の引数の罠!正しい順番をマスターしてエラーを回避しよう
山崎講師2025年10月26日Pythonの「浅いコピー」と「深いコピー」の違いとは?コピーの罠を徹底解説!
山崎講師2025年10月26日VSCodeを自分好みに育てる!新人エンジニアのためのsettings.json徹底ガイド