Python イテレータ

Note: イテレータは数えられる値を含むオブジェクトです。

Python イテレータ

イテレータは、順次アクセス可能なオブジェクトであり、すべての値をトラバースできます。

技術的には、Pythonでは、イテレータはイテレータプロトコルを実装したオブジェクトであり、そのメソッドに __iter__()__next__() が含まれます。

イテレータ vs イテラブル

リスト、タプル、辞書、セットはすべてイテラブルオブジェクトです。これらはイテレータを取得できるイテラブルコンテナです。

これらのオブジェクトはすべて、イテレータを取得するために使用される iter() メソッドを持っています:

mytuple = ("apple", "banana", "cherry")
myit = iter(mytuple)

print(next(myit))
print(next(myit))
print(next(myit))

文字列もイテラブルオブジェクトであり、イテレータを返すことができます:

mystr = "banana"
myit = iter(mystr)

print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))

イテレータをループで回す

forループを使用してイテラブルオブジェクトをイテレートすることもできます:

mytuple = ("apple", "banana", "cherry")

for x in mytuple:
  print(x)

mystr = "banana"

for x in mystr:
  print(x)

forループは実際にはイテレータオブジェクトを作成し、各ループごとに next() メソッドを実行します。

イテレータの作成

イテレータとしてオブジェクト/クラスを作成するには、オブジェクトに __iter__()__next__() メソッドを実装する必要があります。

Pythonのクラス/オブジェクトの章で学んだように、すべてのクラスには __init__() 関数があり、オブジェクトが作成されるときに初期化を行うことができます。

__iter__() メソッドは似たような動作をしますが、操作(初期化など)を行うことができますが、常にイテレータオブジェクト自体を返さなければなりません。

__next__() メソッドも操作を行うことができ、シーケンス内の次のアイテムを返さなければなりません。

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self

  def __next__(self):
    x = self.a
    self.a += 1
    return x

myclass = MyNumbers()
myiter = iter(myclass)

print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))

StopIteration

上記の例は、十分な next() 文があれば永遠に続くでしょう。

無限に続くことを防ぐために、StopIteration 文を使用することができます。

__next__() メソッドで、指定された回数のイテレーションが終了した場合にエラーを発生させる終了条件を追加することができます:

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self

  def __next__(self):
    if self.a <= 20:
      x = self.a
      self.a += 1
      return x
    else:
      raise StopIteration

myclass = MyNumbers()
myiter = iter(myclass)

for x in myiter:
  print(x)