Python カスタム イテレータ

Salman Mehmood 2023年6月21日
  1. Python でクラス メソッド __iter____next__ を使用してカスタム イテレータを作成する
  2. Python のジェネレーターを使用してカスタム イテレーターを作成する
Python カスタム イテレータ

この記事では、イテレーターとは何か、そして __iter__ および __next__ と呼ばれるクラス メソッドを使用してカスタム イテレーターを作成する方法を学びます。 また、Python のジェネレーターを使用してカスタム イテレーターを作成する方法も学習します。

Python でクラス メソッド __iter____next__ を使用してカスタム イテレータを作成する

イテレータと言うと、その名の通り反復に使われます。

C、C++、Java などの言語を使用している場合は、共通の概念 ++ があります。 繰り返しについて話すとき、もう 1つの概念が知られています: for ループです。

5つの要素のリストがあるとします。 ループを使用すると、最初の要素から最後の要素まで繰り返すことができます。

このようにして、いくつかの値を持つリストがあり、インデックス番号を使用してそれらを 1つずつ出力したい場合。

インデックス 0 を渡すと、最初の要素 2 が返されます。インデックス値 1 を使用すると、2 番目の要素 5 が返されます。

Numbers = [2, 5, 10, 3, 1]

print(Numbers[0])
print(Numbers[1])

出力:

2
5

値を出力するもう 1つの方法は、ループを使用することです。 リストを繰り返し処理して、すべての値を出力できます。

Numbers = [2, 5, 10, 3, 1]

for i in Numbers:
    print(i)

出力:

2
5
10
3
1

もう 1つの方法があります。イテレータを使用することです。 一般に、反復子は for ループの舞台裏で動作します。

iter() 関数を使用して、リストをイテレーターに変換するイテレーターを理解します。 この反復子は、すべての値を提供するわけではありません。 一度に 1つの値のみを指定します。

Numbers = [2, 5, 10, 3, 1]

ITR = iter(Numbers)
print(ITR)

イテレータのオブジェクトを出力していることがわかります。

<list_iterator object at 0x000001FEDCFF7310>

ただし、値が必要な場合は、組み込みメソッドである ITR.__next__() を設定できます。 特定のオブジェクトに対する __next__() メソッドの最初の呼び出し中に最初の値が得られます。 これは、インデックス値を使用したのと同じ方法ですが、インデックス値を使用する必要がないという利点があります。

umbers = [2, 5, 10, 3, 1]

ITR = iter(Numbers)
print(ITR.__next__())

出力:

2

次の実行行で ITR.__next__() を実行すると、次の値が返されます。 このシーンの背後では、反復子は複数の値を持つため、__next__() メソッドを呼び出すと、1つの値が取得されます。

繰り返しますが、__next__() を呼び出すと、i の最後の値を認識します。つまり、最後の値の状態を保持します。 これが反復子の優れた点です。 関数を再度呼び出すと、古い値が保持されます。

クラスを使用してイテレータを作成できます。 このクラスを使用して、上位 10 個の値を個別に出力できます。

これを実現するために、TopValues というクラスを用意し、このクラスでカウンターを指定します。

そのために、__init__ 関数を使用します。ここで、カウンター変数 self.N=1 を定義します。 明らかに、カウンターは 1 から初期化されます。カスタム イテレーターを作成するには、2つの重要なメソッドが必要です。

最初のものは iter() メソッドで、イテレータのオブジェクトを提供し、次に next() メソッドが次の値またはオブジェクトを提供します。 __next__ メソッドでは、self.N を返す代わりに、VALUE という変数を使用して self.N を代入し、次の行で self.N を 1 増やします。 .

self.N は次の繰り返しでインクリメントされるため、次の反復ごとにインクリメントされ、self.N ではなく VALUE が返されます。

class TopValues:
    def __init__(self):
        self.N = 1

    def __iter__(self):
        return self

    def __next__(self):
        VALUE = self.N
        self.N += 1
        return VALUE

TopValues クラスのオブジェクトを作成できるように、イテレータの準備が整いました。 通常、反復子がある場合はループを使用できるため、ループを使用しましょう。

T_Val = TopValues()

for i in T_Val:
    print(i)

このコードを実行すると、何千もの値が得られます。

1
2
3
4
5
....
1000

何が起こっているのかを理解しようとしましょう。 イテレータが機能しているかどうかを確認するには、__next__() を使用します。

print(T_Val.__next__())

この行は最初の反復値 1 を出力しますが、ループで何が問題になるのでしょうか? 問題は、ループが最初から最後まで続くことです。 終了は 10 になると想定しましたが、どこで終了するかについては言及していません。

ループを使用すると、next() 関数が呼び出されます。 for ループは内部的に next() 関数を使用します。 したがって、この next() 関数を何度も呼び出します。

__next__ メソッド内で条件を適用する必要があります。

else ブロックも設定する必要があります。 このブロック内で、例外を発生させます。 それ以外の場合、10 個の値を出力した後、ループは None 値を出力します。

class TopValues:
    def __init__(self):
        self.N = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.N <= 10:
            VALUE = self.N
            self.N += 1
            return VALUE
        else:
            raise StopIteration


T_Val = TopValues()

for i in T_Val:
    print(i)

出力:

1
2
3
4
5
6
7
8
9
10

Python のジェネレーターを使用してカスタム イテレーターを作成する

同じことを行うジェネレーター関数を作成してみましょう。 ジェネレーターは、__iter__() および __next__() メソッドを処理してくれるので、はるかに単純です。

Our_Gen() というジェネレーター関数を作成しようとすると、この関数内でパラメーターを渡します。

リストをループしているため、一度に 1つの項目を生成しています。 そして、ループする項目がなくなると、自動的に処理され、反復停止の例外が発生します。

Our_Gen() 関数をループしているので、一度に 1つの項目を出力する必要があります。 これを実行すると、一度に 1つずつ取得できることがわかります。

def Our_Gen(n_list):
    for i in n_list:
        yield i


Func = Our_Gen([2, 5, 10, 3, 1])

for i in Func:
    print(i)

出力:

2
5
10
3
1

next() 関数がまだ機能していることを確認します。 実行後、反復停止例外を受け取る 5つの要素を取得します。

def Our_Gen(n_list):
    for i in n_list:
        yield i


Func = Our_Gen([2, 5, 10, 3, 1])

print(Func.__next__())
print(Func.__next__())
print(Func.__next__())
print(Func.__next__())
print(Func.__next__())
print(Func.__next__())

出力:

2
5
10
3
1
Traceback (most recent call last):
  File "c:\Users\Dell\Desktop\demo\demo.py", line 56, in <module>
    print(Func.__next__())
StopIteration

ジェネレーターは、クラスよりも簡単に作成できます。 しかし、ユースケースによっては、クラスで __iter__() メソッドと __next__() メソッドを実行する方法を知る必要がある場合があります。

カスタム イテレータの作成について詳しくは、こちら を参照してください。

著者: Salman Mehmood
Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

関連記事 - Python Iterator