Почему Python рассматривает кортежи, списки, наборы и словари как принципиально разные вещи? - PullRequest
22 голосов
/ 05 августа 2011

Одной из причин, по которой я люблю Python, является выразительная мощь / ограниченное программирование, обеспечиваемое кортежами, списками, наборами и словарями. Как только вы поймете, что такое списки и некоторые базовые шаблоны, используя IN и FOR, жизнь станет намного лучше! Питон скалы.

Однако мне непонятно, почему эти конструкции обрабатываются так же, как они, и как это меняется (становится незнакомым) с течением времени. Вернувшись в Python 2.x, я мог бы привести аргумент, что все они были просто вариациями базового типа коллекции, и это было отчасти раздражающим, что некоторые неэкзотические сценарии использования требуют от вас преобразования словаря в список и обратно , (Разве словарь не является просто списком кортежей с определенным ограничением уникальности? Разве список не является просто набором с другим видом ограничения уникальности?).

Теперь в мире 3.x все стало сложнее. Теперь есть именованные кортежи - они начинают больше походить на специальный словарь. Теперь есть упорядоченные словари, которые начинают больше походить на список. И я только что увидел рецепт заказанных наборов. Я могу представить, что это происходит и продолжается ... как насчет уникальных списков и т. Д.

Дзен Питона говорит: «Должен быть один - и желательно только один - очевидный способ сделать это». Мне кажется, что это изобилие типов специализированных коллекций находится в противоречии с этой заповедью Python.

Что думают хардкорные Pythonistas?

Ответы [ 8 ]

14 голосов
/ 05 августа 2011

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

Именованные кортежи в основном служат для создания интерфейса stat ()и тому подобное, более удобное в использовании, а также может быть полезно при работе с наборами строк SQL.

Большое объединение, которое вы ищете, действительно существует в форме различных протоколов доступа (getitem, getattr, iter, ...), которые эти типы смешивают и сопоставляют по назначению.

14 голосов
/ 05 августа 2011

tl; dr (duck-typing)

Вы правы, когда видите некоторые сходства во всех этих структурах данных. Помните, что в python используется тип "утка" (если он выглядит как утка и крякает как утка, значит, это утка).Если вы можете использовать два объекта в одной и той же ситуации, то для ваших текущих намерений и целей они также могут быть одного типа данных.Но вы всегда должны помнить, что если вы попытаетесь использовать их в других ситуациях, они могут больше не вести себя одинаково.

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

Изменчивость (можете ли вы ее изменить?)

Вы можете вносить изменения в словари, списки,и устанавливает.Кортежи не могут быть «изменены» без создания копии.

  • Изменяемый: dict, list, set

    Неизменный: tuple

Python string также является неизменяемым типом.Почему мы хотим некоторые неизменные объекты?Я бы перефразировал из этот ответ:

  1. Неизменяемые объекты можно оптимизировать много

  2. В Python,только неизменяемые объекты являются хэшируемыми (и только хэшируемые объекты могут быть членами наборов или ключами в словарях).

При сравнении этого свойства списки и кортежи кажутся "ближайшими"два типа данных.На высоком уровне кортеж является неизменяемой версией списка в виде стоп-кадра.Это делает списки полезными для наборов данных, которые будут меняться с течением времени (поскольку вам не нужно копировать список, чтобы изменить его), но кортежи полезны для таких вещей, как словарные ключи (которые должны быть неизменяемого типа).

Упорядочение (и примечание по абстрактным типам данных)

Словарь, как и набор, не имеет внутреннего концептуального порядка.Это в отличие от списков и кортежей, которые имеют порядок.Порядок элементов в dict или множестве составляет абстрагированный от программиста, что означает, что если элемент A предшествует B в цикле for k in mydata, вы не должны (и вообще не может) полагаться на существо A до B, как только вы начнете вносить изменения в mydata.

  • Сохранение заказа: list, tuple

    Сохранение без заказа: dict, set

Технически, если вы повторяете mydata дважды подряд, это будет в том же порядке, но это более удобная особенность механики python, а на самом деле не является частью set * 1068.* абстрактный тип данных (математическое определение типа данных).Списки и кортежи действительно гарантируют порядок, особенно кортежи, которые являются неизменяемыми.

То, что вы видите, когда выполняете итерацию (если она идет как утка ...)

  • One«элемент» на «элемент»: set, list, tuple

    Два «элемента» на «элемент»: dict

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

Прямые ответы на ваши вопросы

Разве словарь не является просто списком кортежей с определенным ограничением уникальности?

Нет, есть несколько отличий.Словари не имеют собственного порядка, который отличается от списка, который имеет.

Кроме того, словарь имеет ключ и значение для каждого "элемента".С другой стороны, кортеж может иметь произвольное количество элементов, но каждый из которых содержит только значение.

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

Самое главное, однако, элементы словаря могут быть изменены, а кортежи - нет.

Разве список - это не просто набор с уникальной уникальностью? ограничение

Опять же, я бы подчеркнул, что наборы не имеют внутреннего порядка, а списки - нет. Это делает списки гораздо более полезными для представления таких вещей, как стеки и очереди, где вы хотите иметь возможность помнить порядок, в котором вы добавляли элементы. Наборы не дают такой гарантии. Тем не менее, они предлагают преимущество в том, что могут выполнять поиск членов в постоянное время, в то время как списки занимают линейное время.

Теперь есть именованные кортежи - они начинают больше походить на специальный словарь. Теперь есть упорядоченные словари, которые начинают больше походить на список. И я только что увидел рецепт заказанных наборов. Я могу представить, что это происходит и продолжается ... как насчет уникальных списков и т. Д.

В какой-то степени я согласен с вами. Однако библиотеки структур данных могут быть полезны для поддержки общих сценариев использования для уже хорошо зарекомендовавших себя структур данных. Это позволяет программисту не тратить время на попытки найти собственные расширения стандартных структур. Пока это не выходит из-под контроля, и мы по-прежнему видим уникальную полезность в каждом решении, хорошо иметь колесо на полке, поэтому нам не нужно его изобретать заново.

Отличным примером является класс Counter (). Этот специализированный словарь был полезен мне больше раз, чем я могу сосчитать (badoom-tshhhhh!), И он спас меня от усилий по написанию собственного решения. Я бы предпочел иметь решение, которое сообщество помогает мне разрабатывать и придерживаться надлежащих лучших практик Python, а не того, что хранится в моей папке пользовательских структур данных и используется только один или два раза в год.

2 голосов
/ 05 августа 2011

Прежде всего, заказанные словари и именованные кортежи были введены в Python 2, но это не относится к делу.

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

Первое различие между типами коллекций - изменчивость. tuple и frozenset являются неизменяемыми типами. Это означает, что они могут быть более эффективными, чем list или set.

Если вы хотите что-то, к чему вы можете получить доступ случайно или по порядку, но в основном это изменится в конце, вам нужен list. Если вы хотите что-то, что вы также можете изменить в начале, вы хотите deque.

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

dict и set принципиально отличаются от lists и кортежей`. Они хранят хэш своих ключей, позволяя вам увидеть, находится ли элемент в них очень быстро, но требует ли ключ быть хэшируемым. Вы не получаете ту же скорость тестирования членства со связанными списками или массивами.

Когда вы переходите к OrderedDict и NamedTuple, вы говорите о подклассах встроенных типов, реализованных в Python, а не в C. Они предназначены для особых случаев, как и любой другой код в стандартная библиотека, которую вы должны импортировать . Они не загромождают пространство имен, но их приятно иметь, когда они вам нужны.

Однажды вы будете кодировать, и вы скажете: «Чувак, теперь я знаю точно что они имели в виду под« Должен быть один - и предпочтительно только один » очевидный способ сделать это », set это просто , что мне нужно для этого, я так рад, что это часть языка Python! Если бы мне пришлось использовать список, это заняло бы навсегда «. Тогда вы поймете, почему существуют эти разные типы.

1 голос
/ 05 августа 2011

Все эти специализированные типы коллекций предоставляют определенные функциональные возможности, которые недостаточно или эффективно обеспечиваются «стандартными» типами данных list, tuple, dict и set.

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

Эти дополнительные типы данных, которые вы видите как комбинации или вариации базовых, фактически заполняют пробелы в функциональности, оставленные базовыми типами данных.С практической точки зрения, если бы ядро ​​или стандартная библиотека Python не предоставляли эти типы данных, тогда любой, кто нуждался в них, придумал бы свои собственные неэффективные версии.Они используются реже, чем базовые типы, но достаточно часто, чтобы оправдать предоставление стандартных реализаций.

1 голос
/ 05 августа 2011

Словарь индексируется по ключу (фактически это хеш-карта);общий список кортежей не будет.Вы можете утверждать, что оба должны быть реализованы как отношения с возможностью добавления индексов по желанию, но на практике оптимизированные типы для общих случаев использования удобнее и эффективнее.

Добавляются новые специализированные коллекциипотому что они достаточно распространены, так что многие люди в конечном итоге реализуют их, используя более простые типы данных, и тогда у вас возникнут обычные проблемы с переизобретением колес (напрасная трата усилий, отсутствие взаимодействия ...).И если бы Python просто предлагал совершенно общую конструкцию, то у нас было бы много людей, спрашивающих «как реализовать набор с использованием отношения» и т. Д.

(кстати, я использую отношение в математическойили смысл БД)

0 голосов
/ 05 августа 2011

Дзен Питона говорит: «Должен быть один - и желательно только один - очевидный способ сделать это». Мне кажется, что это множество специализированных типов коллекций находится в противоречии с этой заповедью Python.

Не удаленно. Здесь делается несколько разных вещей. Мы выбираем правильный инструмент для работы. Все эти контейнеры созданы по образцу проверенных, проверенных и настоящих концепций CS десятилетиями.

Словари не похожи на кортежи: они оптимизированы для поиска по значению ключа. Кортеж также неизменен, что отличает его от списка (вы можете думать о нем как о frozenlist). Если вы конвертируете словари в списки и обратно, вы почти наверняка делаете что-то не так; пример поможет.

Именованные кортежи существуют для удобства и предназначены для замены простых классов, а не словарей. Упорядоченные словари - это просто обертка, чтобы запомнить порядок, в котором вещи были добавлены в словарь. И ни одна из них не является новой в 3.x (хотя может быть и лучшая языковая поддержка для них; я не смотрел).

0 голосов
/ 05 августа 2011

Мир структур данных (не зависящих от языка) обычно сводится к нескольким небольшим базовым структурам - спискам, деревьям, хеш-таблицам и графам и т. Д., А также к вариантам и их комбинациям. Каждый из них имеет свою конкретную цель с точки зрения использования и реализации.

Я не думаю, что вы можете сделать что-то вроде сокращения словаря в список кортежей с определенным ограничением уникальности без фактического указания словаря. Словарь имеет специальное назначение - поиск по ключу / значению - и реализация структуры данных обычно адаптируется к этим потребностям. Наборы во многом похожи на словари, но определенные операции над наборами не имеют смысла в словаре (объединение, дизъюнкция и т. Д.).

Я не вижу, чтобы это нарушало «Дзен Питона», когда мы делаем что-то одно. Хотя вы можете использовать отсортированный словарь, чтобы делать то, что словарь делает, не используя отсортированную часть, вы все больше нарушаете бритву Оккама и, вероятно, вызываете снижение производительности. Я считаю, что это отличается от способности синтаксически делать что-то по-другому, как в Perl.

0 голосов
/ 05 августа 2011

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

И есть еще один способ сделать это - каждый тип выполняет свою работу.

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