ProgrammingPythonバックエンド開発者

Pythonにおけるfor-inループはどのように機能しますか?このメカニズムをサポートするためにどのようなインフラストラクチャが提供されており、カスタムオブジェクトをイテレートする際に「内部で」何が起こるのでしょうか?

Hintsage AIアシスタントで面接を突破

回答。

Pythonのfor-inループは、特別な2つのメソッド__iter__()__next__()に基づくイテレーションプロトコルを通じて実装されています。ループが始まると、Pythonはiter(obj)を呼び出し(__iter__メソッドを探索)、イテレータが返されると、その__next__()メソッドを呼び出して次の要素を取得します。

要素が正常に発行されると、イテレーションは続きます。StopIteration例外が発生すると、ループは終了します。

カスタムイテレータの例:

class Counter: def __init__(self, low, high): self.current = low self.high = high def __iter__(self): return self def __next__(self): if self.current > self.high: raise StopIteration else: self.current += 1 return self.current - 1 for num in Counter(1, 3): print(num) # 1, 2, 3が出力されます

注意点: 多くの標準Python構造体はイテレータプロトコルを実装しており、あなた自身のオブジェクトも同様にできます。

トリック質問。

Pythonの任意のオブジェクトでfor-inループを使用できますか?イテラブルオブジェクトとイテレータの違いは何ですか?

回答: いいえ、for-inループはオブジェクトがイテラブルである必要があり、つまり__iter__()メソッドを実装し、イテレータ(__next__()メソッド付きのオブジェクト)を返す必要があります。イテレータは__iter__()を通じて自分自身を返しますが、イテラブルオブジェクトはそうではありません。

例:

lst = [1, 2, 3] iterator = iter(lst) print(hasattr(lst, '__iter__')) # True print(hasattr(iterator, '__next__')) # True (イテレータ) print(hasattr(lst, '__next__')) # False (イテレータではない)

知識不足による実際のエラーの例。


ストーリー

プロジェクト: 大きなファイルの処理。

問題: プロジェクトでは、ファイルオブジェクトを2回繰り返し(ファイルの行に対してイテレート)ようとしましたが、新しいファイルを明示的に開かないまま、2回目のイテレーションでは何も得られませんでした(ポインタはすでにファイルの最後にあります!)。


ストーリー

プロジェクト: 自分のコレクションクラスをフレームワークに統合。

問題: クラスは__getitem__のみを実装し、__iter__を実装していなかったため、ジェネレーターや標準のループ(for)と互換性がありませんでした。そのため、イテレータを期待していたサードパーティライブラリが破損しました。


ストーリー

プロジェクト: カスタムコレクションでのmap/filterの使用。

問題: 自分のリストクラスは__iter____next__を実装せず、多くの標準関数と互換性がなく、統合テスト後にのみ明らかになり、大規模なリファクタリングが必要でした。