Для чего нужен кортеж? - PullRequest
       23

Для чего нужен кортеж?

44 голосов
/ 03 сентября 2008

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

Ответы [ 10 ]

52 голосов
/ 03 сентября 2008
  • Кортежи используются всякий раз, когда вы хотите вернуть несколько результатов из функции.
  • Поскольку они неизменяемы, их можно использовать в качестве ключей для словаря (списки не могут).
18 голосов
/ 03 сентября 2008

Кортежи создают хорошие словарные ключи, когда вам нужно объединить более одного фрагмента данных в ваш ключ и не хочется создавать для него класс.

a = {}
a[(1,2,"bob")] = "hello!"
a[("Hello","en-US")] = "Hi There!"

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

8 голосов
/ 07 сентября 2008

Мне нравится это объяснение .

В основном, вы должны использовать кортежи, когда существует постоянная структура (1-я позиция всегда содержит один тип значения, а вторая - другой и т. Д.), И списки следует использовать для списков однородных значений.

Конечно, всегда есть исключения, но это хорошее общее руководство.

3 голосов
/ 25 сентября 2018

Лучший способ думать об этом:

  • Кортеж - это запись , чьи поля не имеют имен.
  • Вы используете кортеж вместо записи, если не можете указать имена полей.

Так что вместо того, чтобы писать что-то вроде:

person = {"name": "Sam", "age": 42}
name, age = person["name"], person["age"]

Или еще более многословный:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person = Person("Sam", 42)
name, age = person.name, person.age

Вы можете просто написать:

person = ("Sam", 42)
name, age = person

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

Кортежи происходят из мира функционального программирования (Haskell, OCaml, Elm, F # и т. Д.), Где они обычно используются для этой цели. В отличие от Python, большинство функциональных языков программирования имеют статическую типизацию (переменная может содержать только один тип значения, и этот тип определяется во время компиляции). Статическая типизация делает роль кортежей более очевидной. Например, на языке вяз:

type alias Person = (String, Int)

person : Person
person = ("Sam", 42)

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

Вышесказанное резко контрастирует со списками , которые должны иметь переменную длину (количество элементов обычно отличается в каждом списке, и вы пишете функции для добавления и удаления элементов) и каждого элемента в списке, как правило, того же типа. Например, у вас будет один список людей и другой список адресов - вы не будете смешивать людей и адреса в одном списке. Принимая во внимание, что смешивание разных типов данных внутри одного кортежа - это и есть смысл кортежей Поля в кортеже обычно бывают разных типов (но не всегда - например, у вас может быть кортеж (Float, Float, Float) для представления координат x, y, z).

Кортежи и списки часто являются вложенными. Распространено иметь список кортежей. Вы можете иметь список кортежей Person так же, как список объектов Person. Вы также можете иметь поле кортежа, значением которого является список. Например, если у вас есть адресная книга, в которой один человек может иметь несколько адресов, у вас может быть кортеж типа (Person, [String]). Тип [String] обычно используется в функциональных языках программирования для обозначения списка строк. В Python вы не будете записывать тип, но вы можете использовать подобные кортежи точно таким же образом, поместив объект Person в первое поле кортежа и список строк во второе поле.

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

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

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

В Python (с использованием реализации CPython по умолчанию) кортежи также быстрее, чем объекты или словари, для большинства целей, поэтому они иногда используются по этой причине, даже если именование полей с использованием объекта или словаря будет более понятным. *

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

from collections import namedtuple

Person = namedtuple("Person", "name age")

person = Person("Sam", 42)
name, age = person.name, person.age

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

Неизменяемые списки очень полезны для многих целей , но тема слишком сложна, чтобы отвечать здесь. Суть в том, что вещи, которые не могут измениться, легче рассуждать, чем вещи, которые могут измениться. Большинство программных ошибок происходят из-за непредвиденных изменений, поэтому ограничение способов их изменения - хороший способ устранения ошибок. Если вам интересно, я рекомендую прочитать учебник для функционального языка программирования, такого как Elm, Haskell или Clojure (Elm - самый дружелюбный). Разработчики этих языков считали неизменность настолько полезной, что все списки неизменны там. (Вместо того, чтобы изменять список для добавления или удаления элемента, вы создаете новый список с добавленным или удаленным элементом . Неизменность гарантирует, что старая копия списка никогда не изменится, поэтому компилятор и среда выполнения может заставить код работать хорошо, повторно используя части старого списка в новом и собирая мусор оставшиеся части, когда они более необходимы.)

3 голосов
/ 03 сентября 2008

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

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

Типичными примерами являются фиксированные данные в приложении, такие как подразделения компании, категории и т. Д. Если эти данные изменяются, обычно один производитель перестраивает кортеж.

2 голосов
/ 22 сентября 2016

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

Кортеж - это список значений через запятую:

t = 'p', 'q', 'r', 's', 't'

рекомендуется заключать кортежи в скобки:

t = ('p', 'q', 'r', 's', 't') 
2 голосов
/ 03 сентября 2008

Я считаю их полезными, когда вы всегда имеете дело с двумя или более объектами в виде набора.

1 голос
/ 03 сентября 2008

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

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

1 голос
/ 03 сентября 2008

Список всегда может заменить кортеж в отношении функциональности (за исключением, очевидно, ключей в dict). Тем не менее, кортеж может заставить вещи идти быстрее. То же самое верно, например, для неизменяемых строк в Java - когда вам когда-нибудь понадобится изменить строки? Никогда!

Я только что прочитал достойную дискуссию об ограничении того, что вы можете сделать, чтобы создавать лучшие программы; Почему Почему Функциональное программирование имеет значение

0 голосов
/ 09 сентября 2008

В дополнение к местам, где они синтаксически необходимы, например, операция string%, и для множественных возвращаемых значений я использую кортежи как форму легких классов. Например, предположим, что у вас есть объект, который передает непрозрачный файл cookie вызывающей стороне из одного метода, который затем передается в другой метод. Кортеж - это хороший способ упаковки нескольких значений в этот файл cookie без определения отдельного класса для их хранения.

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

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