2017-03-02 1 views
4

저는 이터레이터를 한동안 작성 해왔고, 나는 그것을 이해했다고 생각했습니다. 그러나 나는 오늘 밤에 어떤 이슈로 고심하고 있었고, 그걸 가지고 노는 것이 많을수록 내가 더 혼란스러워졌습니다.반복기 프로토콜. 어둠의 마법인가?

반복기의 경우 __iter__next (또는 __next__)을 구현해야한다고 생각했습니다. 그리고 처음 반복기를 반복 할 때 __iter__ 메서드가 호출 될 것이고 nextStopIteration이 호출 될 때까지 호출됩니다.

나는 출력은 2 4 6입니다

class Iter(object): 

    def __iter__(self): 
     return iter([2, 4, 6]) 

    def next(self): 
     for y in [1, 2, 3]: 
      return y 

iterable = Iter() 
for x in iterable: 
    print(x) 

불구하고이 코드를 실행합니다. 따라서 __iter__이 호출되고 있지만 next은 호출되지 않습니다. 그건 내가 찾은 문서와 일치하는 것 같습니다 here. 그러나 그때 내 마음 속에는 더 많은 질문이 제기됩니다.

next 구현이 아닌 컨테이너 유형과 반복기의 차이점은 무엇입니까? 어떻게 내 수업이 어떤 방식으로 취급 될지 미리 알 수 있습니까? 그리고 가장 중요한 것은 for x in Iter()을 사용할 때 next 메서드가 호출되는 클래스를 작성하려면 어떻게해야합니까?

답변

6

목록은 반복 가능이지만, 반복자가 아닙니다.입니다. 비교와 대조 : 목록을 만들고 그 목록의 내용을 반복위한 새로운 반복자 객체를 반환에

>>> type([]) 
list 
>>> type(iter([])) 
list_iterator 

iter를 호출. 그 객체는 요소 1, 2를 산출에 대해 아무것도 모르는, 그래서 개체에서

, 당신은 여기에

def __iter__(self): 
    return iter([2, 4, 6]) # <-- you're returning the list iterator, not your own 

3. 부합하는보다 근본적인 구현의, 목록 [2, 4, 6] 이상, 특히 반복자를리스트 반복자를 반환 파이썬 2의 이터레이터 프로토콜로,리스트 반복자, 생성자 또는 무엇이든 전혀 의지해서 문제를 혼동하지 않는다.

class Iter(object): 

    def __iter__(self): 
     self.val = 0 
     return self 

    def next(self): 
     self.val += 1 
     if self.val > 3: 
      raise StopIteration 
     return self.val 
+0

나는 돌아갈 것이라고 생각한다. 그래서 모든 반복자는 반복자이지만 모든 반복자가 반복자는 아닙니다. 그리고 iterable을 반복 할 때, 나는 iter 메소드가 리턴하는 것이 무엇이든지 반복하고있다. 반복기 또는 생성기 중 어떤 것이 될 수 있습니까? –

+0

수정. 모든 반복자는 반복 가능합니다. 모든 iterables가 iterator는 아닙니다 (예를 들어, 목록은 반복 가능하지만'next'를 구현하지 않기 때문에 iterator가 아닙니다).객체에 대한 반복은 객체에서'iter()'를 호출하여 반환되는 객체에 대해 수행됩니다. 그것은 반드시 반복자를 반환해야합니다 (생성자는 반복자 유형입니다). – wim

+0

고맙습니다. 나는 밤의 시작에 그 모든 것을 알고 있다고 생각하지만 밤의 시작에 대해서도 생각했다. 그러나 또한 매우 잘못된 몇 가지 다른 것들을 생각했다. –

2

는 사용자가 링크 문서에 따르면, 반복자의 __iter__ 방법 자체를 반환 할 예정이다. 그래서 당신의 반복자는 전혀 반복자가 아닙니다 : for이 반복자를 얻기 위해 __iter__을 호출 할 때, 당신은 그것을 iter([2,4,6])으로 줄 것입니다, 그러나 그것을 self에게 주어야합니다. 이 1이라고 할 때마다 반환하고 StopIteration을 제기 결코 당신이 다음 반복자가 무한 스트림 반복자 것, __iter__을 고정한다면 :

은 (또한, 나는 당신의 next 방법은 당신이 무슨 의도하지 생각하지 않습니다. 유한 한 목록 [1, 2, 3]보다는 오히려 부작용이다.)

+0

그래,이 코드는 난센스 다. 내가 스스로에게 증명하려고했던 점은 반복되는 객체가 내 '__iter__'메소드가 반환하는 객체이고, 'next'메소드는 절대로 호출되지 않는다는 것입니다. 어쩌면 피곤해서 잠자리에 들지 않아도 될지 모르지만 나는'다음 '방법이 어떻게 불려지는지 정말로 이해하지 못합니다. –

+0

@GreeTreePython :'next' 메서드는'__iter__'에 의해 반환 된 iterator의'next' 메서드입니다. – ruakh