LINUX.ORG.RU

Непонятки в Python

 ,


0

1

Изучаю Python по книге Learning Python 5E.

Дошел до Chapter 4, где рассказывается про списки (lists). Смутил один пример.

Итак, имеется матрица:

>>> M = [[1, 2, 3], # A 3 × 3 matrix, as nested lists
         [4, 5, 6], # Code can span lines if bracketed
         [7, 8, 9]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Сперва показывается работа с map, которая для над каждым элементом M совершает действие sum:

>>> list(map(sum, M)) # Map sum over items in M
[6, 15, 24]

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

>>> {sum(row) for row in M} # Create a set of row sums
{24, 6, 15}

Причем, если генерить словарь, результат «нормальный»:

>>> {i : sum(M[i]) for i in range(3)} # Creates key/value table of row sums
{0: 6, 1: 15, 2: 24}

Внимание, вопрос: обьяните различие в результатах. Почему в первом случае результат 6, 15, 24, во втором 24, 6, 15, а в третьем снова 6, 15, 24?

Спасибо

лист не сортируется. словарь всегда находится в отсортированном виде. в третьем варианте сортировка происходит по ключу.

anonymous
()

А в питоновском словаре никогда порядок элементов предугадать невозможно. Зачем в этом примере словарь, понять тоже тяжело. Попробуй заменить словарь на список, типа

[sum(row) for row in M]
yvv ★★☆
()
Ответ на: комментарий от anonymous

лист не сортируется

имелось в виду - автоматически. ты можешь его сортануть и результат будет такой же, как со словарём из второго примера

anonymous
()

Порядок элементов в словаре был не гарантирован до определенной версии.

vvn_black ★★★★★
()
Ответ на: комментарий от anonymous

еще раз глянул на пример из ОП - действительно муть какая-то. тоже интересно почему именно такой порядок значений во втором варианте

anonymous
()

оказывается, питоновский словарь реализован через хештаблицу, соответственно порядок элементов зависит от алгоритма хеширования

anonymous
()

В первом варианте создается генератор, который используется для создания списка. Он обрабатывает элементы по порядку и добавляет их (суммы) в список по тому же порядку.

Во втором создается set - неупорядоченное(!) множество элементов

anonymous
()

Почему в первом случае результат 6, 15, 24, во втором 24, 6, 15, а в третьем снова 6, 15, 24

В первом случае у тебя список, он хранит порядок добовления элементов. Во втором - множество, множества порядок не хранят. БОлее того, они хранят только уникальные элементы. В третьем - словарь, они хранят порядок начиная с версии 3.7 (в 3.6 это было частично)

Dred ★★★★★
()
Ответ на: комментарий от Dred

Во втором - множество, множества порядок не хранят.

Конкретно это питоновское множество. Например, std::set реализован через красно-черное дерево, т.е. по дефолту упорядочен, а std::unordered_set - через хештаблицу. Но адептам питона такие сложности ни к чему, у них сет всегда неупорядочен :)

anonymous
()
Ответ на: комментарий от anonymous

Конкретно это питоновское множество

эм, ну да. Накой черт ты сюда свои плюсы притащил ? Или когда из под анона пишешь не в состоянии отличить структуру данных от ее реализации ?

Dred ★★★★★
()
Последнее исправление: Dred (всего исправлений: 1)
Ответ на: комментарий от Dred

Или когда из под анона пишешь не в состоянии отличить структуру данных от ее реализации ?

Я как раз это хотел подчеркнуть, set зависит от реализации и она бывает разной. В stl по дефолту одна реализация, а в конкретной версии питона другая, а еще где-то третья...

anonymous
()

Кому должен?

anonymous
()

У тебя и в словаре элементы могли не соответствовать порядку в списке. Только недавно в Python 3 встроенные словари стали повторять поведение OrderedDict, т.е. запоминать порядок добавления элементов и воспроизводить его при доступе.

Virtuos86 ★★★★★
()
Ответ на: комментарий от yvv

Вообще-то в новой версии языка можно вполне побыть телепатом и предугадать, и уже достаточно давно, лол.

anonymous
()

во втором случае у тебя множество, в них порядок элементов не сохраняется

>>> {6, 15, 24} # вывод может быть другой, и случайно совпасть с исходным
{24, 6, 15}
>>> {6, 15, 24} == {24, 6, 15} # всегда True
True

в первом случае список, с ним все хорошо. map() возвращает итератор, который раздает элементы в исходном порядке, list() создает список, также сохраняя порядок

в третьем случае у тебя словарь, который по идее работает так же как множество, но хеширует ключи (0, 1, 2), а не значения, поэтому порядок мог получиться другой. чисто случайно порядок получился правильный. ну и нужно упомянуть, что с версии 3.6/3.7 словари в питоне сохраняют порядок элементов.

анонимуса выше игнорируй, он чушь несет

MyTrooName ★★★★★
()
Последнее исправление: MyTrooName (всего исправлений: 1)
Ответ на: комментарий от yvv

А, я просто до сих пор 2.7 использую.

там же есть «машина времени», ты её не юзаешь? :)

Sahas ★★★★☆
()
Последнее исправление: Sahas (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.