Почему map возвращает объект map вместо списка в 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.х все изменилось:
Python 3.5.1
In[2]: map(lambda x: x+1, [1,2,3])
Out[2]: <map at 0x4218390>
Я понимаю как, но я не мог найти ссылку на почему. Почему языковые дизайнеры сделали этот выбор, который, на мой взгляд, приносит много боли. Это было для армрестлинга разработчикам вставлять в список понимание?
ИМО, список можно, естественно, думал, как функторы; и мне почему-то казалось, что я думаю так:
fmap :: (a -> b) -> f a -> f b
4 ответа:
Я думаю, что причина, почему карта все еще существует на всех, когда выражений генератор также существует, что он может принимать несколько аргументов итератора, которые все зациклены и передаются в функцию:
>>> 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]))
в противном случае он просто ничего не добавляет над выражениями генератора.
поскольку он возвращает итератор, он не сохраняет полный список размеров в памяти. Так что вы можете легко перебирать его в будущем, не делая никакой боли в памяти. Возможно, вы даже не нужен полный список, но часть его, пока ваше состояние не будет достигнуто.
вы можете найти docs полезно, итераторы являются удивительными.
объект, представляющий поток данных. Повторные вызовы итератора
__next__()
метод (или передача его встроенная функцияnext()
) возвращает последовательные элементы в потоке. Когда больше нет данных aStopIteration
вместо этого возникает исключение. На этом этапе объект итератора исчерпан и любые дальнейшие вызовы его__next__()
метод просто поднятьStopIteration
снова. Итераторы должны иметь__iter__()
метод, который возвращает сам объект итератора, поэтому каждый итератор также итеративен и может использоваться в большинстве мест, где принимаются другие итераторы. Одним из заметных исключений является код, который пытается пройти несколько итераций. Объект контейнера (например,list
) создает новый итератор каждый раз, когда вы передать его
Гвидо отвечает на этот вопрос здесь: "так как создание списка было бы просто расточительно".
он также говорит, что правильное преобразование использовать обычный
for
петли.преобразование
map()
от 2 до 3 может быть не просто простой случай воткнувlist( )
вокруг него. Гвидо тоже говорит:" если входные последовательности не одинаковой длины,
map()
остановит на прекращении самого короткого из последовательности. Для полной совместимости сmap()
из Python 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))
работает просто отлично, мало затрат на строительство