クラス

【Python】イテレータ(iterator)の基本

【Python】イテレータ(iterator)の基本
naoki-hn

Python におけるイテレータ(iterator)の基本について解説します。

イテレータ(iterator)

イテレータ(iterator)とは

イテレータ(iterator)は、繰り返し処理に必要な特殊メソッドを実装したオブジェクトで、オブジェクトの要素を順に取り出すために使用されます。ここでの特殊メソッドとは、イテレータプロトコルを実現する以下の 2 つのメソッドのことです。

メソッド名概要
__next__()コンテナの次の要素を返す
__iter__()イテレータ自身を返す

Python を学んでいるとイテラブル(iterable)という言葉を聞くことがあるかと思います。イテラブルとは、for文で要素として 1 つずつ取り出せるような反復可能なオブジェクトのことです。代表的なものとして、リスト(list)、タプル(tuple)、辞書(dict)等があります。

__iter__() メソッドか、もしくは __getitem__() メソッドを持つ任意のクラスのオブジェクトもイテラブルです。イテラブルに関する公式ドキュメントの説明はこちらを参照してください。

イテレータは、イテラブルオブジェクトから __iter__() メソッドを使って生成されるオブジェクトであり、__next__() メソッドを通じて順に要素を取り出すことができるものです。

組み込み関数の iter() に以下の例のようにシーケンス(文字列等)を渡すとイテレータを作成することができます。1 つずつ値を取り出せることを見てみましょう。

sample = "python"

# イテレータを作成
i = iter(sample)
print(type(i))

# 値を順に取り出す
print(next(i))
print(next(i))
print(next(i))
print(next(i))
print(next(i))
print(next(i))
# 全て取り出し終わるとStopIteration例外となる
print(next(i))
【実行結果】
<class 'str_ascii_iterator'>
p
y
t
h
o
n
Traceback (most recent call last):
...(省略)...
StopIteration

上記のように iter 関数に文字列を渡すと str_ascii_iterator というイテレータが作成されます。このイテレータを通じて値の順次取り出しが可能です。

イテレータは、next 関数に渡すと順に値を取り出すことができ、例では "p""y""t""h""o""n"と順に文字列の値が取り出されています。

値を全て取り出し終わると、イテレータは StopIteration 例外を送出します。for 文では、この StopIteration 例外を自動でとらえてループが終了するようになっているので、イテレータは for 文で使用することができます。

独自のカスタムイテレータ(iterator)の作成方法

イテレータ(iterator)は、特殊メソッドの __next__() メソッドと __iter__() メソッドを実装したコンテナオブジェクトです。これらのメソッドを自分で実装することで、独自のカスタムイテレータを作成することができます。

例えば、数値をカウントダウンする MyCountDown クラスという簡単なクラスを作ってみましょう。

class MyCountDown:
    """カウントダウンイテレータ"""

    def __init__(self, count):
        self.count = count

    def __next__(self):
        """次の値を返す"""
        # 繰り返しの終わりではStopIteration例外を送出する
        if self.count <= 0:
            raise StopIteration
        # カウントダウン
        self.count -= 1
        # 次の値を返す
        return self.count

    def __iter__(self):
        """イテレータの状態を返す"""
        # イテレータ自身を返却
        return self


def main():
    count_iter = MyCountDown(5)
    for c in count_iter:
        print(c)


if __name__ == "__main__":
    main()
【実行結果】
4
3
2
1
0

MyCountDown クラスの __next__() メソッドでは、count1 減らして値を返却します。マイナスの値になった際には StopIteration 例外を送出(raise)するようになっています。また、__iter__() メソッドでは、イテレータ自身の self を返却します。

main 関数内で MyCountDown クラスのオブジェクトを作成し、for 文で使用しながら値を出力しています。値のカウントダウンができ、終了時には for 文を抜けていることが分かります。

このように、__next__() メソッドや __iter__() メソッドを自分で作成することで独自のカスタムイテレータを作成することが可能です。

itertools ~効率的なループ実行のためのイテレータ生成関数~

Python のライブラリにイテレータの使い方としてよくあるパターンを実装した itertools と呼ばれるライブラリがあります。itertools を使うことでイテレータを簡単に活用することが可能です。

for 文でよく使われる zip の説明をしている「zipを用いたfor文の使い方 ~複数のリストをまとめて処理~」のページでも、itertoolszip_longest を紹介しています。通常の zip が要素の少ない方にあわせて処理をするのに対して、itertoolszip_longest は要素数が多い方にあわせて足りない部分を補完して処理したい場合に使用します。

itertools の公式ドキュメントはこちらを参照してください。

まとめ

Python におけるイテレータ(iterator)の基本について解説しました。

イテレータ(iterator)とは、繰り返しに必要な特殊メソッドを実装したイテラブル(iterable)なコンテナオブジェクトの事を言います。

イテレータは順番に要素を1つずつ取り出すことができfor文で利用することができます。また、イテレータは __next__() メソッドや __iter__() メソッドを自分で実装することで独自のカスタムイテレータを作成することも紹介しました。

イテレータは、Python でも重要な概念の1つなので、ぜひ概要を理解してもらえたらと思います。

イテレータはジェネレータの基礎にもなっています。ジェネレータについては「ジェネレータ(generator)関数 ~yieldによる返却~」でも紹介していますので参考にしてください。

ソースコード

上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。

あわせて読みたい
【Python Tech】プログラミングガイド
【Python Tech】プログラミングガイド
ABOUT ME
ホッシー
ホッシー
システムエンジニア
はじめまして。当サイトをご覧いただきありがとうございます。 私は製造業のメーカーで、DX推進や業務システムの設計・開発・導入を担当しているシステムエンジニアです。これまでに転職も経験しており、以前は大手電機メーカーでシステム開発に携わっていました。

プログラミング言語はこれまでC、C++、JAVA等を扱ってきましたが、最近では特に機械学習等の分析でも注目されているPythonについてとても興味をもって取り組んでいます。これまでの経験をもとに、Pythonに興味を持つ方のお役に立てるような情報を発信していきたいと思います。どうぞよろしくお願いいたします。

※キャラクターデザイン:ゼイルン様
記事URLをコピーしました