2017-05-08 11 views
1

저는 파이썬의 생성기, 반복기, 반복기를 배우고 있는데 왜 다음과 같은 것이 작동하지 않는지 설명 할 수 없습니다. 나는 운동으로 zip 함수의 간단한 버전을 만들고 싶다. 여기에 내가했던 일이야 : 내가 할 것은발전기의 정지 그림

def myzip(*collections): 

    iterables = tuple(iter(collection) for collection in collections) 

    yield tuple(next(iterable) for iterable in iterables) 

test = myzip([1,2,3],(4,5,6),{7,8,9}) 

print(next(test)) 
print(next(test)) 
print(next(test)) 

: 일부 컬렉션의 튜플은 내가 collections

  • 나는 인 (여기서, 각각의 컬렉션에 대한 새로운 튜플 iterables을 만들
  • iterable)을 사용하여 반복자를 얻습니다. iter
  • 그런 다음 각 반복 가능한 반복에 대해 next이라고하는 새 튜플을 만듭니다. 이 튜플은 yield이다.

그래서 처음 실행시 객체 iterables이 생성 (및 저장) 될 것으로 예상됩니다. 그런 다음 각 반복 (첫 번째 반복 포함)에서 전에 저장 한 모든 반복 가능 항목에 대해 next을 호출하여이를 반환합니다.

그러나 이것은 내가 무엇을 얻을 수 있습니다 :

(1, 4, 8) 
--------------------------------------------------------------------------- 
StopIteration        Traceback (most recent call last) 
<ipython-input-108-424963a58e58> in <module>() 
     8 
     9 print(next(test)) 
---> 10 print(next(test)) 

StopIteration: 

그래서 나는 첫 번째 반복 괜찮 것을 확인하고 올바른 결과입니다. 그러나 두 번째 반복은 StopIteration 예외를 발생시키고 이유를 이해하지 못합니다. 각 반복 가능은 여전히 ​​일부 값을 가지므로 next 중 하나도 StopIteration을 반환하지 않습니다. 사실,이 작품 :

def myziptest(*collections): 

    iterables = tuple(iter(collection) for collection in collections) 

    for _ in range(3): 
     print(tuple(next(iterable) for iterable in iterables)) 

test = myziptest([1,2,3],(4,5,6),{7,8,9}) 

출력 :

(1, 4, 8) 
(2, 5, 9) 
(3, 6, 7) 

그래서 무슨 일이 일어나고 있는지? 덕분에 많은

답변

1

는 다음 작업 솔루션을

def myzip(*collections): 

    iterables = tuple(iter(collection) for collection in collections) 

    while True: 
     try: 
      yield tuple([next(iterable) for iterable in iterables]) 
     except StopIteration: 
      # one of the iterables has no more left.     
      break 

test = myzip([1,2,3],(4,5,6),{7,8,9}) 

print(next(test)) 
print(next(test)) 
print(next(test)) 

이 코드의 차이를 그리고 당신은 당신의 코드는 결과를 얻을 수 있다는 것입니다. 의미, 전화 다음 한 번 이상 당신에게 StopIteration 줄 것이다.

yield x을 대기열에 넣고 next을 해당 대기열에서 터뜨리는 것으로 생각하십시오. 그리고 빈 큐에서 팝업을 시도하면 Stopiteration이됩니다. 넣을 수있는만큼 많이 팝 할 수 있습니다.

+0

그건 정말 어리석은 실수 였어. 사이클을 추가하는 것을 잊어 버렸으므로 함수가 첫 번째 next() 이후에 죽었다. 감사합니다. – edoedoedo

+1

문제 없습니다. 참고로, 반복문에서 iterable을위한 '튜플 (다음 (iterable))'은 같은 크기가 아닌 콜렉션이 있더라도 계속 작동합니다. 'tuple (iterable에서 iterable을위한 next (iterable))'을 만들면 StopIteration을 트리거 할 것이므로 가장 짧은 공통 길이로 멈출 수 있습니다. – algrebe

+0

사실 나는 테스트를 위해 내가한다면 : print (i)'나는 끝없는 반복을 얻는다. 차이점이 뭐야? – edoedoedo