Pythonでは、forループを使用して、コンテナオブジェクトの要素を反復できます。コンテナオブジェクトには、リスト(list)、タプル(tuple)、ディクショナリ(dict)、セット(set)などが含まれます。しかし、なぜこれらのオブジェクトをforループを使用して操作できるのでしょうか。
まず、試す簡単なクラスを定義します。
classTestRange:
def __init__(self, num):
self.num = num
for i inTestRange(10):print(i)
# 出力
Traceback(most recent call last):
File "<stdin ", line 1,in<module
TypeError:'TestRange' object is not iterable
エラーメッセージは、「TestRange」オブジェクトが反復可能なオブジェクトではないことを示しています。では、反復可能なオブジェクトとは何ですか?
反復可能なオブジェクトでは、 __iter__
の魔法のメソッドを実装する必要があり、このメソッドの戻り値は反復子である必要があります。では、イテレーターとは何ですか?
イテレーターは、 __next__
マジックメソッドを実装するだけで済みます。
例としてリストを見てください:
nums =[13,12,33]
iter_ret = nums.__iter__() #xにはこのメソッドがあり、リストが反復可能であることを示し、メソッドは反復子を返します
iter_ret
< list_iterator object at 0x100f32198
iter_ret.__next__()13
iter_ret.__next__()12
iter_ret.__next__()33
iter_ret.__next__()Traceback(most recent call last):
File "<stdin ", line 1,in<module
StopIteration
分析:
上に示したように、 __iter__
メソッドはリストnumsに実装され、イテレーターが返され、 __next__
メソッドがイテレーターに実装されます。 __next__
を呼び出すプロセスでは、 StopIteration
のエラーが発生するまで要素をnumsで返します。
実際、forステートメントの機能は似ています。 ** forステートメントの内部メカニズムは**:
__iter__
メソッドが存在するかどうかを判断します。存在する場合は、 __iter__
メソッドを呼び出して反復子を返します。それ以外の場合は、TypeError例外を直接スローします。__next__
メソッドは継続的に呼び出され、各呼び出しは現在の値を順番に繰り返し取得します。以前のTestRangeは、イテレータープロトコルに2つのメソッドを実装していなかったため、エラーを報告しました。今後も改善を続けてください。
classTestRange:
def __init__(self, _max):
self.i =0
self._max = _max
def __iter__(self):return self
def __next__(self):if self.i < self._max:
i = self.i
self.i +=1return i
else:
# 停止条件に達すると、この例外がスローされます
raise StopIteration()
# テストを実行します
for i inTestRange(3):print(i)
# 出力
012
分析:
このクラスはすでに __next__
メソッドを実装しているため、このクラスに基づいて作成されたオブジェクト自体がイテレーターです。また、反復可能オブジェクトには __iter__
メソッドが必要であり、反復子を返す必要があるため、 __iter__
はオブジェクト自体を self
します。
総括する
これまで、Python-forループの内部メカニズムに関するこの記事を紹介しました。関連するpython forループのコンテンツについては、ZaLou.Cnの以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後、ZaLou.Cnをさらにサポートしていただければ幸いです。 !