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__()
メソッドを実行する方法を知る必要がある場合があります。
カスタム イテレータの作成について詳しくは、こちら を参照してください。
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