Python プログラミングの効率と柔軟性を高める:collections.abc.Iterator を中心としたイテレーション戦略


イテレータオブジェクトのインターフェース

collections.abc.Iterator ABC は、次の 1 つの抽象メソッドを定義します。

  • next() メソッド:イテレータオブジェクトから次の要素を返します。このメソッドは、イテレータが要素を使い果たした場合に StopIteration 例外を発生させる必要があります。

イテレータオブジェクトの使用例

collections.abc.Iterator ABC を実装するオブジェクトは、for ループで使用できます。次の例は、リスト内の要素をループする方法を示しています。

numbers = [1, 2, 3, 4, 5]

for number in numbers:
  print(number)

このコードは次の出力を生成します。

1
2
3
4
5

イテレータオブジェクトの作成

collections.abc.Iterator ABC を実装するオブジェクトは、さまざまな方法で作成できます。最も一般的な方法は、コレクションオブジェクトの __iter__() メソッドを呼び出すことです。次の例は、リストのイテレータを作成する方法を示しています。

numbers = [1, 2, 3, 4, 5]

iterator = iter(numbers)

このコードは、numbers リストのイテレータオブジェクトを作成します。iterator オブジェクトを使用して、リスト内の要素をループできます。

while True:
  try:
    number = next(iterator)
    print(number)
  except StopIteration:
    break

このコードは、numbers リスト内の要素をすべてループし、各要素をコンソールに出力します。

イテレータオブジェクトの利点

イテレータオブジェクトには、次の利点があります。

  • 柔軟性:イテレータオブジェクトは、コレクション内の要素をさまざまな方法でループするために使用できます。たとえば、イテレータオブジェクトを使用して、コレクション内の要素を反復処理したり、特定の条件を満たす要素のみを処理したりできます。
  • メモリ効率:イテレータオブジェクトは、コレクション内のすべての要素を一度にメモリにロードする必要がありません。代わりに、イテレータオブジェクトは、必要に応じて 1 つの要素ずつ生成します。

collections.abc.Iterator ABC は、Python のコレクション内の要素をループするための強力で柔軟なツールです。イテレータオブジェクトを使用すると、メモリ効率と柔軟性を向上させることができます。

  • collections.abc.Iterator ABC は、Python の標準ライブラリの一部である itertools モジュールで提供されるさまざまなイテレータユーティリティで使用されます。
  • collections.abc.Iterator ABC を実装するオブジェクトは、必ずしもコレクションオブジェクトである必要はありません。たとえば、ジェネレータオブジェクトは、collections.abc.Iterator ABC を実装するオブジェクトです。
  • collections.abc.Iterator ABC は、Python 3.3 以降で使用できます。


リストの要素をループする

この例では、collections.abc.Iterator を使ってリストの要素をループする方法を示します。

numbers = [1, 2, 3, 4, 5]

# イテレータを作成する
iterator = iter(numbers)

# 次の要素を取得する
while True:
    try:
        number = next(iterator)
        print(number)
    except StopIteration:
        break
1
2
3
4
5

ファイルの行をループする

この例では、collections.abc.Iterator を使ってファイルの行をループする方法を示します。

with open('myfile.txt') as f:
    # イテレータを作成する
    iterator = iter(f)

    # 次の行を取得する
    while True:
        try:
            line = next(iterator)
            print(line.strip())
        except StopIteration:
            break

このコードは、myfile.txt ファイル内の各行をコンソールに出力します。

この例では、カスタムイテレータを作成する方法を示します。このイテレータは、偶数のみを返すように設計されています。

class EvenNumbersIterator:
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.start > self.end:
            raise StopIteration

        number = self.start
        self.start += 2

        return number

# イテレータを作成する
iterator = EvenNumbersIterator(1, 10)

# 次の要素を取得する
while True:
    try:
        number = next(iterator)
        print(number)
    except StopIteration:
        break
2
4
6
8
10


collections.abc.Iterator の代替手段として最も一般的な方法は、ジェネレータを使用することです。ジェネレータは、関数を使用してイテレータオブジェクトを作成する構文です。ジェネレータは、メモリ効率が高く、柔軟性に優れています。

次の例は、ジェネレータを使用して偶数のみを返す方法を示しています。

def even_numbers(start, end):
    for number in range(start, end + 1, 2):
        yield number

# イテレータを作成する
iterator = even_numbers(1, 10)

# 次の要素を取得する
while True:
    try:
        number = next(iterator)
        print(number)
    except StopIteration:
        break

このコードは、collections.abc.Iterator を使用する前の例と同じ出力を生成します。

for ループを使用する

一部のケースでは、for ループを使用して明示的にイテレーションを行う方が、ジェネレータよりもシンプルで読みやすい場合があります。

次の例は、リストの要素を for ループを使用してループする方法を示しています。

numbers = [1, 2, 3, 4, 5]

# リストの要素をループする
for number in numbers:
    print(number)

特定のライブラリを使用する

特定のタスクには、collections.abc.Iterator よりも適したライブラリが存在する場合があります。たとえば、ファイルの行をループするには、itertools.islice 関数を使用できます。

次の例は、itertools.islice 関数を使用して myfile.txt ファイルの最初の 3 行をループする方法を示しています。

with open('myfile.txt') as f:
    # 最初の 3 行のイテレータを作成する
    iterator = itertools.islice(f, 3)

    # 次の行を取得する
    for line in iterator:
        print(line.strip())

このコードは、myfile.txt ファイルの最初の 3 行をコンソールに出力します。