Pythonのイテレータとは?iter関数やnext関数の使い方や独自のクラスをイテレータにする方法

スポンサーリンク

Pythonのイテレータは、反復処理可能なオブジェクトです。

このような反復をサポートするあらゆる種類のオブジェクトはイテレータと呼ばれます。

さて、あなたは混乱するかもしれません。

iterableという別のオブジェクトが存在します。

それは何でしょうか?見てみましょう。


スポンサーリンク

イテレータとイテラブル

イテレート可能なオブジェクトは、反復処理が可能なオブジェクトです。

つまり、イテレータを使ってこのオブジェクトの中を移動することができる。

イテレート可能なオブジェクトの例としては、タプル、リスト、文字列、配列などがあります。

イテレート可能なオブジェクトからイテレータを生成するには、iter() メソッドを用いる。

iterable_list = [1, 2, 3]
iterable_string = "Hello"
 
iterator_1 = iter(iterable_list)
iterator_2 = iter(iterable_string)
 
print(iterator_1, type(iterator_1))
print(iterator_2, type(iterator_2))

結果は以下の通りです。

<list_iterator object at 0x7f887b01aed0> <class 'list_iterator'>
<str_iterator object at 0x7f887b01af50> <class 'str_iterator'>

出力は、リストと文字列の2つのイテレータが作成されたことを示しています。

ここで、イテレータオブジェクトがサポートするメソッドを見てみましょう。


Python イテレータメソッド

イテレータオブジェクトには iter() と next() と呼ばれる2つの特別なメソッドがあります。

iter()`メソッドは、イテレートからPythonイテレータオブジェクトを取得するために使用されました。

次に、イテレータを走査するために、 next() メソッドを使用してイテレータブルの次の要素を取得します。

形式です。

next_iterable_object = next(iterator)

移動する要素がなくなると、これは終了し、 StopIteration 例外を発生させます。

これを説明するために、リストイテレータのすべての要素を表示してみましょう。

>>> iterable_list = [1, 2, 3]
>>> iterator_1 = iter(iterable_list)
>>> next(iterator_1)
1
>>> next(iterator_1)
2
>>> next(iterator_1)
3
>>> next(iterator_1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

見ての通り、イテレータの長さを超えると、確かに StopIteration Exception を発生させます。

さて、次のステップに進みましょう。


Python で独自のイテレータを構築する

どんなイテレータオブジェクトも、走査可能な要素数を持っています。

しかし、独自のイテレータを作るにはどうしたらよいのでしょうか?独自のクラスを作成する必要があります。

Pythonでは、イテレータを作るには、イテレータプロトコルと呼ばれるプロトコルが必要です。

このプロトコルには __iter__()__next__() という特定のメソッドがあり、一般的なイテレータのメソッドと似ていますが、クラスの中にあるため、区別を示すためにこの記号を前置・後置しています。

iter()next()メソッドは内部でこれらのメソッドを呼び出すので、イテレータを作るには、クラスの内部でiter()next()` メソッドを独自に定義する必要があります。

リストだけを走査し、要素の数が 5 より大きい場合に StopIteration Exception を発生させる単純なイテレータを作成してみましょう。

また、next() メソッドで、これまでにイテレートした要素数を表示することにします。

class MyClass():
    def __init__(self):
        self.counter = 0
        # Set the limit
        self.limit = 5
 
    def __iter__(self):
        # The iter() method internally calls this
        print('Call to __iter__()')
        return self
 
    def __next__(self):
        print('Call to __next__()')
        if self.counter > self.limit:
            raise StopIteration
        else:
            # Increment counter and return it
            self.counter += 1
            return self.counter
 
 
# Create the iterable
my_obj = MyClass()
 
# Create the iterator object from the iterable
my_it = iter(my_obj)
 
for i in range(7):
    print(next(my_it))

結果は以下の通りです。

Call to __iter__()
Call to __next__()
1
Call to __next__()
2
Call to __next__()
3
Call to __next__()
4
Call to __next__()
5
Call to __next__()
6
Call to __next__()
Traceback (most recent call last):
  File "iter.py", line 29, in <module>
    print(next(my_it))
  File "iter.py", line 15, in __next__
    raise StopIteration
StopIteration

ここでは、1から6までの数字を表示していますが、次の呼び出しでは、限界を超えたため、 StopIteration 例外を発生させます。

私たちは独自のイテレータを作りました。


まとめ

この記事を読んで、イテレータについてよく理解し、この概念に関する疑問が解消されたことでしょう。

もしそうでなければ、下のコメント欄で質問してください。


参考文献

  • イテレータに関する JournalDev の記事

タイトルとURLをコピーしました