Почему коллекции не обрабатываются единообразно в Python? - PullRequest
6 голосов
/ 14 сентября 2010

Наборы и списки обрабатываются по-разному в Python, и, похоже, не существует единого способа работы с обоими. Например, добавление элемента в set выполняется методом add, а для list - методом append. Я знаю, что за этим стоит другая семантика, но есть и общая семантика, и часто алгоритм, который работает с некоторыми коллекциями, больше заботится об общности, чем о различиях. C ++ STL показывает, что это может работать, так почему же в Python такого понятия нет?

Редактировать: В C ++ я могу использовать output_iterator для хранения значений в (почти) произвольном типе коллекции, включая списки и наборы. Я могу написать алгоритм, который принимает такой итератор в качестве аргумента и записывает в него элементы. Алгоритм тогда совершенно не зависит от типа контейнера (или другого устройства, может быть файлом), который поддерживает итератор. Если резервный контейнер является набором, который игнорирует дубликаты, то это решение вызывающей стороны. Моя конкретная проблема заключается в том, что это происходило со мной несколько раз, когда я использовал, например, list для определенной задачи, а затем решил, что set более уместно. Теперь я должен изменить append на add в нескольких местах в моем коде. Мне просто интересно, почему Python не имеет понятия для таких случаев.

Ответы [ 3 ]

6 голосов
/ 14 сентября 2010

Прямой ответ: это недостаток дизайна.

Вы должны быть в состоянии вставить в любой контейнер, где имеет смысл общая вставка (например, исключая dict) с тем же именем метода.Должно быть последовательное, общее имя для вставки, например.add, что соответствует set.add и list.append, так что вы можете добавлять в контейнер, не заботясь о том, что вы вставляете.

Использование разных имен для этой операции в разных типахявляется необоснованным несоответствием и устанавливает плохой базовый стандарт: библиотека должна поощрять пользовательские контейнеры использовать согласованный API, а не предоставлять в значительной степени несовместимые API для каждого базового контейнера.в этом случае: в большинстве случаев, когда результаты функции представляют собой список элементов, реализуйте его как генератор.Они позволяют обрабатывать оба из них последовательно (с точки зрения функции), а также другие формы итерации:

def foo():
    yield 1
    yield 2
    yield 3

s = set(foo())
l = list(foo())
results1 = [i*2 for i in foo()]
results2 = (i*2 for i in foo())
for r in foo():
    print r
4 голосов
/ 14 сентября 2010

добавить и добавить отличаются . Наборы неупорядочены и содержат уникальные элементы, в то время как append предполагает, что элемент всегда добавляется, и что это делается специально в конце.

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

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

1 голос
/ 14 сентября 2010

Фактическая причина, вероятно, просто связана с историей Python.

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

Вы можете обвинить автора оригинального модуля, если хотите, но имейте в виду, что пользовательские типы и встроенные типы обязательно жили в разных вселенных вплоть до Python 2.2, что означало, что вы не могли напрямую расширять встроенный модуль.и, возможно, позволили авторам модулей чувствовать себя нормально, не поддерживая согласованную семантику коллекции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...