Pythonにおけるリストとイテレータの動作仕様と相違点

Pythonの組み込みデータ構造であるリストは、頻繁に使用されるコレクションですが、その内部的な振る舞いはイテレータ(iterator)とは明確に区別されます。この違いは、プロトコルの実装要件、メモリ消費特性、およびデータアクセスの柔軟性に現れます。

反復可能オブジェクトとイテレータプロトコル

リストは反復可能(iterable)ですが、イテレータではありません。Pythonの言語仕様において、反復可能オブジェクトは__iter__メソッドを実装しているだけで十分です。リストはこのメソッドを持ち、for文やコレクション操作で直接呼び出せます。一方、イテレータはさらに__next__メソッドを持つ必要があり、状態を保持して次の要素を逐次返します。リスト自体には__next__が存在しないため、単体ではイテレータとして機能しません。

source_data = ["alpha", "beta", "gamma"]
for position, element in enumerate(source_data):
    print(f"位置 {position}: {element}")

リストからイテレータを生成するには、組み込み関数iter()を使用します。生成されたイテレータはnext()関数を通じて要素を取得しますが、全要素を消費するとStopIteration例外を送出します。

items = ["alpha", "beta", "gamma"]
sequence_iter = iter(items)
try:
    while True:
        current_item = next(sequence_iter)
        print(current_item)
except StopIteration:
    pass

メモリ管理とアクセスパターンの差異

リストとイテレータの主な相違点は、データの保持方法と再利用性にあります。

  • ストレージ構造とランダムアクセス: リストは連続したメモリ領域に全要素を保持するため、インデックス指定やスライスによる任意の位置へのアクセスがO(1)で可能です。イテレータは内部カーソルまたは状態変数のみを持ち、前方への順序付きアクセスしかサポートしません。
  • 空間計算量: 大量のデータを扱う場合、リストは要素数を比例してメモリを消費します。対照的にイテレータは要素を必要に応じて生成または取得するため、メモリフットプリントはデータサイズに依存せず定数値に抑えられます。この特性は、大規模ファイルのストリーム処理や無限数列の表現において重要な利点となります。
  • 反復の寿命: イテレータは一度完了すると exhausted 状態になり、再度使用するには新たなインスタンスの生成が必要です。リストはデータ構造そのものが不変の状態を保持しているため、複数のループや並列イテレーションを安全に繰り返せます。

タグ: Python iterators list-protocol memory-optimization data-structures

5月16日 05:12 投稿