Python イテレータ
Python イテレータ
イテレータは、反復可能なオブジェクトです。このチュートリアルでは、反復子の仕組みと、__iter__ および __next__ メソッドを使用して独自の反復子を作成する方法を学習します。
ビデオ:Python イテレータ
Python の反復子
イテレータは Python のいたるところにあります。 for
内にエレガントに実装されています ループ、内包表記、ジェネレーターなどですが、目に見えないところに隠されています。
Python の Iterator は、単純に反復可能なオブジェクトです。一度に 1 つの要素でデータを返すオブジェクト。
技術的に言えば、Python の イテレータ オブジェクト __iter__()
という 2 つの特別なメソッドを実装する必要があります。 と __next__()
、まとめてイテレータ プロトコルと呼ばれます .
オブジェクトは iterable と呼ばれます そこからイテレータを取得できれば。リスト、タプル、文字列など、Python のほとんどの組み込みコンテナーは反復可能です。
iter()
関数 (次に __iter__()
を呼び出します) メソッド) からイテレータを返します。
イテレータによる反復
next()
を使用します イテレータのすべての項目を手動で繰り返す関数。最後に到達し、返されるデータがなくなると、StopIteration
が発生します。 例外。以下は例です。
# define a list
my_list = [4, 7, 0, 3]
# get an iterator using iter()
my_iter = iter(my_list)
# iterate through it using next()
# Output: 4
print(next(my_iter))
# Output: 7
print(next(my_iter))
# next(obj) is same as obj.__next__()
# Output: 0
print(my_iter.__next__())
# Output: 3
print(my_iter.__next__())
# This will raise error, no items left
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
loop は任意の iterable を反復できます。 for
がどのように機能するかを詳しく見てみましょう。 loop は実際には Python で実装されています。
for element in iterable:
# do something with element
実際には次のように実装されます。
# create an iterator object from that iterable
iter_obj = iter(iterable)
# infinite loop
while True:
try:
# get the next item
element = next(iter_obj)
# do something with element
except StopIteration:
# if StopIteration is raised, break from loop
break
内部的には for
ループは反復子オブジェクト iter_obj
を作成します iter()
を呼び出して
皮肉なことに、この for
loop は実際には無限の while ループです。
ループ内で next()
を呼び出します 次の要素を取得し、 for
の本体を実行します この値でループします。すべてのアイテムが使い果たされた後、StopIteration
内部でキャッチされ、ループが終了します。他の種類の例外は通過することに注意してください。
カスタム イテレータの構築
Python ではイテレータをゼロから構築するのは簡単です。 __iter__()
を実装するだけです そして __next__()
メソッド。
__iter__()
メソッドは iterator オブジェクト自体を返します。必要に応じて、初期化を実行できます。
__next__()
メソッドは、シーケンス内の次のアイテムを返す必要があります。最後に到達したとき、および後続の呼び出しでは、StopIteration
を発生させる必要があります。 .
ここでは、各反復で次の 2 の累乗を与える例を示します。累乗指数はゼロから始まり、ユーザーが設定した数までです。
オブジェクト指向プログラミングについて何も知らない場合は、Python オブジェクト指向プログラミングにアクセスしてください。
class PowTwo:
"""Class to implement an iterator
of powers of two"""
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
# create an object
numbers = PowTwo(3)
# create an iterable from the object
i = iter(numbers)
# Using next to get to the next iterator element
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()
は 2 つの引数で呼び出すことができます。最初の引数は呼び出し可能なオブジェクト (関数) である必要があり、2 番目の引数はセンチネルです。反復子は、戻り値がセンチネルと等しくなるまでこの関数を呼び出します。
>>> int()
0
>>> inf = iter(int,1)
>>> next(inf)
0
>>> next(inf)
0
int()
が 関数は常に 0 を返します。そのため、iter(int,1)
として渡します。 int()
を呼び出すイテレータを返します 戻り値が 1 になるまで。これは決して起こらず、無限イテレータを取得します。
独自の無限イテレータを構築することもできます。次の反復子は、理論的にはすべての奇数を返します。
class InfIter:
"""Infinite iterator to return all
odd numbers"""
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 ジェネレーターをご覧ください。
Python