Список, возвращаемый функцией map, исчезает после одного использования

Я новичок в Python. Я использую Python 3.3.2, и мне сложно понять, почему следующий код:

strList = ['1','2','3']
intList = map(int,strList)
largest = max(intList)
smallest = min(intList)

Дает мне эту ошибку:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: min() arg is an empty sequence

Однако этот код:

strList = ['1','2','3']
intList = list(map(int,strList))
largest = max(intList)
smallest = min(intList)

Не дает мне никаких ошибок.

Моя мысль заключается в том, что когда intList присваивается возвращаемому значению функции map, он становится итератором, а не списком, согласно docs. И, возможно, в качестве побочного эффекта вызова max(), итератор был итерирован до конца списка, заставляя Python полагать, что список пуст (я рисую из знания C здесь, я не знаком с тем, как итераторы действительно работаю на Python.) Единственное доказательство, которое я должен поддержать, это то, что для первого блока кода:

>>> type(intList)
<class 'map'>

тогда как для второго блока кода:

>>> type(intList)
<class 'list'>

Кто-нибудь может подтвердить или опровергнуть это для меня?

Ответ 1

Вы точно верны. В Python 3, map возвращает итератор, который вы можете перебирать только один раз. Если вы повторите итератор во второй раз, он немедленно поднимет StopIteration, как будто он пуст. max потребляет все это, а min видит, что итератор пуст. Если вам нужно использовать элементы более одного раза, вам нужно вызвать list, чтобы получить список вместо итератора.

Ответ 2

из вашей документации map:

Возвращает итератор, который применяет функцию к каждому элементу итерации, давая результаты.

и http://docs.python.org/3/library/stdtypes.html#typeiter

Как только метод iterators next() вызывает StopIteration, он должен продолжать делать это при последующих вызовах.

Таким образом, итератор, независимо от базового объекта данных, может использоваться только один раз. Он основывается на концепции генератора.

itertools.tee можно использовать несколько независимых итераторов от одного.

l1,l2 = itertools.tee(intList,2)
max(l1)
min(l2)