Список vs кортеж: когда использовать каждый?
Описание проблемы: Разница между списками и кортежами в Python
Я сталкиваюсь с вопросом о том, когда использовать списки, а когда кортежи в Python. У меня есть некоторые представления об их различиях, но возникает необходимость в более четких рекомендациях.
Например, есть случаи, когда выбор за вас не стоит, например, когда вы работаете с оператором форматирования строк:
"hello %s you are %s years old" % x
В этом случае переменная x
должна быть кортежем.
Однако, если я сам разрабатываю API и могу выбирать типы данных, то каковы критерии для принятия решения? В каких ситуациях целесообразнее использовать списки, а в каких - кортежи? Я был бы признателен за советы и рекомендации по данному вопросу.
4 ответ(ов)
В Python существует устойчивая культура, где кортежи (tuples) используются для гетерогенных коллекций, что похоже на использование структур (struct) в C, в то время как списки (lists) предназначены для гомогенных коллекций, аналогично массивам (arrays). Однако мне никогда не удавалось полностью согласовать это с вопросом о мутабельности, упомянутым в других ответах. Мутабельность действительно имеет значение (вы не можете изменить кортеж), в то время как гомогенность не является строгим требованием, и поэтому это кажется менее интересным различием.
Вы правы, и ваше понимание разницы между кортежами и списками в Python верное. Основное различие заключается в том, что кортежи (tuple) являются неизменяемыми (immutable): их содержимое нельзя изменить после присвоения. Списки (list), с другой стороны, изменяемы (mutable): вы можете добавлять элементы, изменять или удалять их.
Поэтому я обычно использую кортежи для данных, которые не должны изменяться после их создания, и списки для тех данных, которые могут изменяться.
Если вы сами разрабатываете API и выбираете типы данных, вот некоторые рекомендации, которые стоит учесть:
Для входных параметров лучше всего использовать самый общий интерфейс, который вам нужен. Чаще это будет не просто кортеж или список, а скорее последовательность, срез или даже итерируемый объект. Используя динамическую типизацию в Python, вы можете избежать множества явных проверок типов, если не нужно в этом строгость.
Что касается данных, которые вы возвращаете (выходные параметры), просто возвращайте то, что вам удобнее всего, например, тип данных, который вы используете в своем коде, или тот, что возвращает ваша вспомогательная функция.
Важно помнить о том, чтобы избегать возвращения списка (или любого другого изменяемого типа), который является частью вашего внутреннего состояния. Например:
class ThingsKeeper:
def __init__(self):
self.__things = []
def things(self):
return self.__things # Внешние объекты могут теперь менять ваше состояние
def safer(self):
return self.__things[:] # Здесь создается копия, что не должно ухудшить производительность
Таким образом, вы защитите свое состояние от нежелательных изменений извне.
Незначительное, но примечательное преимущество списка по сравнению с кортежем заключается в том, что списки обычно более портативны. Стандартные инструменты реже поддерживают кортежи. Например, в JSON нет типа кортежа. В YAML такой тип присутствует, но его синтаксис значительно менее привлекателен по сравнению с синтаксисом списка, который довольно удобен.
В таких случаях вы можете использовать кортежи для внутреннего представления данных, а затем преобразовывать их в списки в процессе экспорта. Альтернативно, можно использовать списки повсеместно для сохранения единообразия.
В чем разница между списками и кортежами?
Как отсортировать список/кортеж списков/кортежей по элементу на заданном индексе
Сортировка списка кортежей по второму элементу (целое значение)
Как получить последний элемент списка?
Как клонировать список, чтобы он не изменялся неожиданно после присваивания?