工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> Python

Pythonイテレータ完全ガイド:仕組みと自作方法

Pythonイテレータ

Pythonイテレータの仕組み、forループやnext()関数での走査、イテレータプロトコルを使ったカスタム/無限イテレータの作成方法を学びます。

動画:Pythonイテレータ

Pythonにおけるイテレータ

イテレータはPythonに遍在します。forループ、リスト内包表記、ジェネレータ、多くの組み込みデータ構造の基盤となっており、しばしば舞台裏で働きます。

イテレータは単にデータを1要素ずつ生成するオブジェクトです。Pythonでは__iter__()と__next__()メソッドを実装したオブジェクトをイテレータと見なします。

イテレータを提供できるオブジェクトをイテラブルと呼びます。リスト、タプル、文字列、辞書などほとんどの組み込みコンテナはイテラブルです。組み込みiter()関数はオブジェクトの__iter__()メソッドを呼んでイテレータを取得します。

イテレータを通したイテレーション

next()関数でイテレータを手動で進められます。イテレータが尽きるとStopIterationが発生します。

# リスト定義
my_list = [4, 7, 0, 3]
# iter()でイテレータ取得
my_iter = iter(my_list)
# next()でイテレーション
# 出力: 4
print(next(my_iter))
# 出力: 7
print(next(my_iter))
# next(obj) == obj.__next__()
# 出力: 0
print(my_iter.__next__())
# 出力: 3
print(my_iter.__next__())
# 要素なしでエラー
next(my_iter)

出力

4 7 0 3 Traceback (most recent call last): File "<string>", line 24, in <module> next(my_iter) StopIteration

より自然なイテレーションはforループで、イテレータライフサイクルを自動処理します。

>>> for element in my_list:
...     print(element)
... 4 7 0 3

forループがイテレータでどう動作するか

forループは内部的に以下に変換されます:

for element in iterable:
    # elementで何かする

これは以下のロジックと等価:

# イテラブルからイテレータオブジェクト作成
iter_obj = iter(iterable)
# 無限ループ
while True:
    try:
        # 次のアイテム取得
        element = next(iter_obj)
        # elementで何かする
    except StopIteration:
        # StopIteration発生でループ脱出
        break

これはforループが本質的にイテレータプロトコルとStopIteration例外に依存する無限ループであることを示しています。

カスタムイテレータの構築

スクラッチからイテレータを作成するのは簡単:__iter__()でイテレータインスタンス(多くの場合self)を返し、__next__()で次の値を生成、終了時にStopIterationを発生させます。

以下はユーザー指定最大指数までの2の累乗を生成する例です。

class PowTwo:
    """2の累乗を生成するイテレータ。"""
    def __init__(self, max=0):
        self.max = max
    def __iter__(self):
        self.n = 0
        return self
    def __next__(self):
        if self.n <= self.max:
            result = 2 ** self.n
            self.n += 1
            return result
        else:
            raise StopIteration
# オブジェクト作成
numbers = PowTwo(3)
# オブジェクトからイテラブル作成
i = iter(numbers)
# nextで次のイテレータ要素へ
print(next(i))
print(next(i))
print(next(i))
print(next(i))
print(next(i))

出力

1 2 4 8 Traceback (most recent call last): File "/home/bsoyuj/Desktop/Untitled-1.py", line 32, in <module> print(next(i)) File "<string>", line 18, in __next__ raise StopIteration StopIteration

カスタムイテレータでのforループ使用も同様にシンプル:

>>> for i in PowTwo(5):
...     print(i)
... 1 2 4 8 16 32

Python無限イテレータ

イテレータは無制限でもよいです。組み込みiter()は呼び出し可能オブジェクトとセンチネル値を受け取り:関数を繰り返し呼び、戻り値がセンチネルと等しくなるまで継続。例:

>>> int()
0
>>> inf = iter(int, 1)
>>> next(inf)
0
>>> next(inf)
0

int()は常に0を返すため、iter(int, 1)はセンチネルを永遠に見ず、無限イテレータを生成します。

独自の無限イテレータも作成可能、例えばすべての奇数を生成するもの:

class InfIter:
    """連続する奇数を返す無限イテレータ。"""
    def __iter__(self):
        self.num = 1
        return self
    def __next__(self):
        num = self.num
        self.num += 2
        return num

実行例:

>>> a = iter(InfIter())
>>> next(a)
1
>>> next(a)
3
>>> next(a)
5
>>> next(a)
7

無限イテレータ使用時は常に終了条件を設け、無限ループを避けてください。

イテレータはオンデマンドでアイテム生成するためメモリ効率的です。理論上、すべての奇数のような無限シーケンスを全体を格納せず生成可能です。

よりシンプルなイテレータ作成法についてはPythonジェネレータ(yield使用)を参照。

Python

  1. Python データ型マスター: 実践ガイド
  2. Python 演算子完全マスター: 包括的ガイド
  3. Python pass文完全マスター: 実践ガイド
  4. Python 関数引数完全マスター: 位置引数・キーワード引数・デフォルト引数
  5. Python辞書完全ガイド:作成、操作、高度なテクニック
  6. Pythonクロージャ解説:ネスト関数が変数を捕捉する仕組み
  7. Python datetimeマスター:日付・時刻・タイムゾーン実践ガイド
  8. Pythonのtime.sleep()をマスター:ベストプラクティス、マルチスレッド、実例
  9. Python 概要:高水準、読みやすい、インタラクティブ、オブジェクト指向
  10. Python 数値型完全ガイド:不変な数値データ型の理解と活用
  11. Python 文字列完全マスター:作成、アクセス、操作のすべて