파이썬의 for-in 루프는 __iter__() 및 __next__()라는 두 개의 특별한 메소드를 기반으로 하는 반복 프로토콜을 통해 구현됩니다. 루프가 시작되면, 파이썬은 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을 출력합니다.
미세 조정: 많은 파이썬의 표준 구조가 이터레이터 프로토콜을 구현하므로, 자신의 객체도 쉽게 그렇게 만들 수 있습니다.
파이썬의 모든 객체에 대해 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 (비 이터레이터)
이야기
프로젝트: 대용량 파일 처리.
문제: 프로젝트에서 파일 객체에 대해 두 번 반복하기 시도했는데 — 두 번째 반복 시 아무 줄도 받지 못했습니다(포인터가 이미 파일 끝에 있었음!).
이야기
프로젝트: 프레임워크와의 콜렉션 클래스 통합.
문제: 클래스가
__getitem__만 구현하고__iter__를 구현하지 않아, 제너레이터 및 표준 루프(for)와 호환되지 않았습니다. 이로 인해 외부 라이브러리가 이터레이터를 예상했기 때문에 문제가 발생했습니다.
이야기
프로젝트: 사용자 정의 컬렉션에서 map/filter 사용.
문제: 자신의 리스트 클래스가
__iter__와__next__를 구현하지 않아, 많은 파이썬의 표준 함수와 호환되지 않았습니다. 이 문제는 통합 테스트 후에 발견되었고, 상당한 재작업이 필요했습니다.