Почему карта возвращает объект карты вместо списка в 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> 

Я понимаю, как, но я не мог найти ссылку на причину. Почему дизайнеры языка сделали этот выбор, который, на мой взгляд, вызывает большую боль. Это было для разработчиков оружия, чтобы придерживаться списков?

ИМО, список можно считать естественным образом как Функторы ; и меня как-то думали думать таким образом:

 fmap :: (a -> b) -> fa -> fb 

4 Solutions collect form web for “Почему карта возвращает объект карты вместо списка в Python 3?”

Я думаю, что причина, по которой карта все еще существует вообще, когда существуют выражения генератора, заключается в том, что она может принимать несколько аргументов итератора, которые все зацикливаются и передаются в функцию:

 >>> 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 исключение StopIteration . На этом этапе объект итератора исчерпан, и любые дальнейшие вызовы его __next__() снова вызывают StopIteration . Итераторы должны иметь __iter__() который возвращает сам объект итератора, поэтому каждый итератор также является итерабельным и может использоваться в большинстве мест, где принимаются другие итерации. Одним из примечательных исключений является код, который пытается выполнить несколько итераций. Объект-контейнер (например, list ) создает новый новый итератор каждый раз, когда вы передаете его функции iter() или используете его в цикле 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) не достигает желаемого результата, потому что полный список уже были построены и сохранены в памяти.

Например, в list(range(n)) Python 3 list(range(n)) работает очень хорошо, поскольку для создания объекта range мало затрат, а затем преобразования его в список. Однако в Python 2 iter(range(n)) не сохраняет память, потому что полный список создается range() до того, как будет создан итератор.

Поэтому в Python 2 для создания итератора требуются отдельные функции, а не список, например imap для map (хотя они не совсем эквивалентны ), xrange для range , izip для zip . В отличие от Python 3 требуется только одна функция, поскольку вызов list() создает полный список, если требуется.

  • Сложность len () в отношении наборов и списков
  • Как установить psycopg2 для Python 3.x?
  • Объект 'str' не имеет атрибута 'decode'. Ошибка Python 3?
  • Какую библиотеку python 3 я должен использовать для MySQL?
  • Восстановление генератора с использованием декоратора
  • Как сделать числа, добавленные в список чисел, применимыми к индексам списка слов без пропущенных чисел
  • Может кто-нибудь объяснить это: 0.2 + 0.1 = 0.30000000000000004?
  • Использование Python 3.3 в примере книги OpenShift
  • Python - лучший язык программирования в мире.