[python] 지도가 Python 3에서 목록 대신지도 객체를 반환하는 이유는 무엇입니까?

Python 3.x새로운 언어 디자인을 이해하는 데 관심이 있습니다 .

나는 Python 2.7에서 기능을 즐긴다 map.

Python 2.7.12
In[2]: map(lambda x: x+1, [1,2,3])
Out[2]: [2, 3, 4]

그러나 Python 3.x에서는 다음과 같이 변경되었습니다.

Python 3.5.1
In[2]: map(lambda x: x+1, [1,2,3])
Out[2]: <map at 0x4218390>

나는 방법을 이해하지만 이유에 대한 참조를 찾을 수 없습니다. 왜 언어 디자이너들이이 선택을했을까요? 제 생각에는 엄청난 고통을 안겨줍니다. 이것이 목록 이해력을 고수하는 팔 씨름 개발자였습니까?

IMO, 목록은 자연스럽게 Functor로 생각할 수 있습니다 . 그리고 나는 어떻게 든 이런 식으로 생각한다고 생각했습니다.

fmap :: (a -> b) -> f a -> f b



답변

나는지도가 여전히 존재 이유를 생각 전혀 할 때 발전기 표현이 또한 존재, 그것은 모든 기능에 이상 루프 및 전달되는 여러 반복자 인수를 취할 수 있다는 것입니다 :

>>> list(map(min, [1,2,3,4], [0,10,0,10]))
[0,2,0,4]

zip을 사용하는 것보다 약간 쉽습니다.

>>> list(min(x, y) for x, y in zip([1,2,3,4], [0,10,0,10]))

그렇지 않으면 단순히 생성기 표현식에 아무것도 추가하지 않습니다.


답변

반복자를 반환하기 때문에 전체 크기 목록을 메모리에 저장하지 않습니다. 그래서 당신은 기억에 어떤 고통도 일으키지 않고 미래에 그것을 쉽게 반복 할 수 있습니다. 아마도 전체 목록이 필요하지는 않지만 상태에 도달 할 때까지 목록의 일부가 필요합니다.

문서는 유용하며 반복자는 훌륭합니다.

데이터 스트림을 나타내는 개체입니다. 반복기의 __next__()메소드 에 대한 반복 호출 (또는 내장 함수에 전달 next())은 스트림에서 연속 항목을 리턴합니다. 더 이상 데이터를 사용할 수 없으면 StopIteration대신 예외가 발생합니다. 이 시점에서 반복기 객체가 소진되고 해당 __next__()메서드에 대한 추가 호출이 StopIteration다시 발생합니다. 반복기에는 __iter__()반복기 객체 자체를 반환 하는 메서드가 있어야 모든 반복기가 반복 가능하며 다른 반복기가 허용되는 대부분의 장소에서 사용될 수 있습니다. 한 가지 주목할만한 예외는 여러 번의 반복을 시도하는 코드입니다. 컨테이너 객체 (예 :)는 사용자가 객체에 list전달할 때마다 새로운 이터레이터를 생성합니다.iter()함수를 사용하거나 for 루프에서 사용하십시오. 반복기로이를 시도하면 이전 반복 단계에서 사용 된 동일한 소진 된 반복기 객체가 반환되어 빈 컨테이너처럼 보입니다.


답변

Guido는 여기 에서이 질문에 대답 합니다 . ” 목록을 만드는 것은 낭비 일 것입니다.”

그는 또한 올바른 변환은 일반 for루프 를 사용하는 것이라고 말합니다 .

map()2에서 3으로 변환 하는 것은 그저 list( )주위에 a를 붙이는 단순한 경우가 아닐 수 있습니다 . Guido는 또한 말합니다 :

입력 시퀀스가 동일한 길이없는 경우 ” map()시퀀스의 짧은 종료에 중지됩니다. 전체의 호환성을 위해 함께 map()파이썬 2.X에서,도에서 시퀀스 포장 itertools.zip_longest(), 예를

map(func, *sequences)

된다

list(map(func, itertools.zip_longest(*sequences)))


답변

Python 3에서 많은 함수 (뿐만 map아니라 zip, range기타)는 전체 목록이 아닌 반복자를 반환합니다. 반복기를 원할 수도 있고 (예를 들어 전체 목록을 메모리에 보관하지 않으려는 경우) 목록을 원할 수도 있습니다 (예 : 색인을 생성 할 수 있어야 함).

그러나 Python 3에서 변경된 주요 이유 는 전체 목록이 이미 작성되어 메모리에 저장되어 있기 때문에 list(some_iterator)역 등가를 사용하여 반복기를 목록으로 변환하는 것이 사소한 일이지만 iter(some_list)원하는 결과를 얻지 못하기 때문이라고 생각합니다.

예를 들어 Python 3 list(range(n))에서는 range객체 를 빌드 한 다음 목록으로 변환하는 데 드는 비용이 거의 들지 않으므로 제대로 작동합니다. 그러나 Python 2 iter(range(n))에서는 range()반복기가 빌드되기 전에 전체 목록이 생성되기 때문에 메모리를 절약하지 않습니다 .

따라서 Python 2에서는 imapfor map(그것이 완전히 동일 하지는 않지만 ), xrangefor range, izipfor 와 같이 목록이 아닌 반복자를 생성하는 데 별도의 함수가 필요합니다 zip. 대조적으로 Python 3는 필요한 경우 list()호출이 전체 목록을 생성하므로 단일 함수 만 필요 합니다.


답변