Pythonにおけるイテレータ(iterator)の基本について解説します。
Contents
イテレータ(iterator)
イテレータ(iterator)とは
イテレータ(iterator)とは、繰り返し処理に必要な特殊メソッドを実装したオブジェクトで、イテラブルオブジェクトの要素を順に取り出すために使用されます。ここで言っている特殊メソッドとは具体的に、イテレータプロトコルを実現する以下の2つのメソッドです。
メソッド名 | 概要 |
---|---|
__next__() | コンテナの次の要素を返す |
__iter__() | イテレータ自身を返す |
Pythonを学んでいるとイテラブル(iterable)という言葉を聞くことがあるかと思います。イテラブルとは、for
文で要素として1つずつ取り出せるような反復可能なオブジェクトのことで、代表的なものとしてリスト(list
)、タプル(tuple
)、辞書(dict
)等があります。__iter__()
メソッドかもしくは__getitem__()
メソッドを持つ任意のクラスのオブジェクトもイテラブルです。イテラブル(iterable)に関する公式ドキュメントの説明はこちらを参照してください。
イテレータは、イテラブルオブジェクトから__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__()
メソッドでは、count
を1
減らして値を返却します。もしマイナスの値になった際にはStopIteration
例外を送出(raise
)するようになっています。また、__iter__()
メソッドでは、イテレータ自身のself
を返却しています。
main
関数内でMyCountDown
クラスのオブジェクトを作成し、for
文で使用しながら値を出力しています。値のカウントダウンができ、終了時にはfor
文を抜けていることが分かります。
このように__next__()
メソッドや__iter__()
メソッドを自分で作成することで独自のカスタムイテレータを作成することが可能です。
itertools ~効率的なループ実行のためのイテレータ生成関数~
Pythonのライブラリにイテレータの使い方としてよくあるパターンを実装したitertools
と呼ばれるライブラリがあります。itertools
を使うことでイテレータを簡単に活用することが可能です。
for
文でよく使われるzipの説明をしている「zipを用いたfor文の使い方 ~複数のリストをまとめて処理~」のページでも、itertools
のzip_longest
を紹介しています。通常のzip
が要素の少ない方にあわせて処理をするのに対して、itertools
のzip_longest
は要素数が多い方にあわせて足りない部分を補完して処理したい場合に使われます。
itertools
には、他にも実装されているものがあるので、また整理してみようかなと思います。
itertools
の公式ドキュメントはこちらを参照してください。
まとめ
Pythonにおけるイテレータ(iterator)の基本について解説しました。
イテレータ(iterator)とは、繰り返しに必要な特殊メソッドを実装したイテラブル(iterable)なコンテナオブジェクトの事を言います。
イテレータは順番に要素を1つずつ取り出すことができfor
文で利用することができます。また、イテレータは__next__()
メソッドや__iter__()
メソッドを自分で実装することで独自のカスタムイテレータを作成することも紹介しました。
イテレータをあえて使用しなくてもプログラム開発ができるわけですが、イテレータはジェネレータの基礎にもなっています。ジェネレータについては「ジェネレータ(generator)関数 ~yieldによる返却~」でも紹介していますので参考にしてください。
上記で紹介しているソースコードについてはgithubにて公開しています。参考にしていただければと思います。