Язык программирования Python предоставляет четыре встроенных типа данных для хранения коллекций из объектов. Все они наделены различными свойствами и характеристиками: list (список), tuple (кортеж), set (множество) и dictionary (словарь).

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

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

Встроенные типы данных Python для хранения коллекций объектов

Зачем вообще выбирать?

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

Может стог сена  —  это список? Как насчет кортежа? Почему бы не использовать множества всегда? На какие предостережения следует обратить внимание?

Давайте разберёмся.

Отличия между списком, кортежем и множеством

  • Отличие 1: дубликаты.
    Говоря проще, List и Tuple в Python как двойняшки разного пола, а тип данных Set для них как двоюродный брат. В отличие от списков или кортежей, множество не содержит дубликатов. Другими словами, элементы множества всегда уникальны. Получается, что множество удобно удаляет дубликаты, словно создано именно для этого.
set_example = {1, 1, 2, 3, 3, 3}
# {1, 2, 3}

fruit_set = {'🍎', '🍓', '🍐', '🍎', '🍎', '🍓'}
# {'🍎', '🍐', '🍓'}
  • Отличие 2: упорядоченность.
    Наверняка вы слышали утверждение “множества и словари в Python не упорядочены”, но на сегодняшний день  —  это лишь половина правды в зависимости от того, какой версией Python вы пользуетесь. До Python версии 3.6 словари и множества действительно не сохраняли порядок элементов, но начиная с Python 3.7, dictionary и set официально упорядочены по времени добавления элементов. А вот list и tuple  —  это всегда упорядоченные последовательности объектов. 
# Пример тогда ещё неупорядоченного множества в Python версии 3.5

fruit_size = {} 
>>> fruit_size['🍎'] = 12 
>>> fruit_size['🍐'] = 16 
>>> fruit_size['🍇'] = 20 
>>> fruit_size
{'🍎': 12, '🍇': 20, '🍐': 16}
  • Отличие 3: индексация.
    Что списки, что кортежи  —  оба поддерживают индексацию и срезы, а вот множества  —  нет.
fruit_list = ['🍎', '🍓', '🍐']
fruit_list[1]
# '🍓'

animal_tuple = ('🐶', '🐱', '🐮')
animal_tuple[2]
# '🐮'

vehicle_set = {'🚐', '🏍', '🚗'}
vehicle_set[0]
# TypeError: 'set' object is not subscriptable

Когда выбирать список, а когда  —  кортеж?

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

a_tuple = tuple(range(1000))
a_list = list(range(1000))

a_tuple.__sizeof__()  # 8024 байта
a_list.__sizeof__()   # 9088 байт
  • Список подходит, если:
  1. Последовательность планируется изменять.
  2. Планируется постепенно добавлять новые элементы в последовательность или удалять старые.
  • Кортеж подходит, если:
  1. Последовательность НЕ планируется изменять.
  2. Все, что нужно от последовательности  —  это возможность поочередно перебирать постоянный набор элементов.
  3. Нужна последовательность элементов для ее назначения в качестве ключа словаря. Поскольку списки  —  это изменяемый тип данных, их нельзя применять в качестве ключей словаря.
  4. Важна скорость выполнения операций с последовательностью: из-за отсутствия возможности изменения, кортежи работают куда быстрее списков.

Когда выбирать множества?

Базовая структура типа данных “множество”  —  это хеш-таблица (Hash Table). Поэтому множества очень быстро справляются с проверкой элементов на вхождение, например содержится ли объект x в последовательности a_set.

Идея заключается в том, что поиск элемента в хэш-таблице  —  это операция O(1), то есть операция с постоянным временем выполнения.

Получается, всегда надо использовать множество?

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

Выводы

“Преждевременная оптимизация  —  корень всех зол”.

Итак, самое главное, что вам стоит запомнить по поводу списков, кортежей и множеств.

  1. Если необходимо хранить дубликаты, то выбирайте список или кортеж.
  2. Если НЕ планируется изменять последовательность после ее создания, то выбирайте кортеж, а не список.
  3. Если НЕ нужно хранить дубликаты, то воспользуйтесь множеством, так как они значительно быстрее определяют наличие объекта в последовательности.

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

Главное  —  помнить о похожих чертах и особенностях встроенных типов данных Python.

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Jerry Ng: Tuples vs. Lists vs. Sets in Python

Предыдущая статьяВнутренняя жизнь React Native
Следующая статьяЧто делает сайты медленнее?