Почему нам нужны кортежи в Python (или какой-либо неизменный тип данных)?

Я прочитал несколько учебных руководств по Python (Погружение В Python для одного), и ссылка языка на Python.org - я не вижу, почему языку нужны кортежи.

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

Неизменность?

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

В C/C++, если я выделяю указатель и указываю на некоторую допустимую память, я не забочусь, где адрес расположен, пока это не является пустым, прежде чем я буду использовать его.

Каждый раз, когда я ссылаюсь на ту переменную, я не должен знать, указывает ли указатель все еще на исходный адрес или нет. Я просто проверяю на пустой указатель и использую его (или не).

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

>>> x='hello'
>>> id(x)
1234567
>>> x='good bye'
>>> id(x)
5432167

x все еще ссылается на данные, которые я хочу, почему кто-либо должен заботиться, является ли его идентификатор тем же или отличающийся?

138
задан Glenn Maynard 1 February 2010 в 03:04
поделиться

9 ответов

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

a = [1,1,1]
doWork(a)

вызывающий абонент не имеет гарантии значения a после вызова. Однако

a = (1,1,1)
doWorK(a)

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

-121--2014930-

Для его получения можно запустить простой запрос XPath:

$parent_div = $div->xpath("parent::*");

И поскольку это Simplexml, и он имеет только узлы элементов и атрибутов, а родительский узел может быть только элементом и никогда не быть атрибутом, можно использовать сокращенный синтаксис:

$parent_div = $div->xpath("..");

(через: Common Xpath Cheats - Simplexml по хакре) )

-121--2121739-

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

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

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

Объекты Python не могут изменить местоположение после того, как они созданы, изменяемы или нет. (Точнее, значение id () не может измениться - глупая вещь, на практике.) Внутреннее место хранения изменяемых объектов может изменяться, но это скрытая деталь реализации.

>>> x='hello'
>>> id(x)
1234567
>>> x='good bye'
>>> id(x)
5432167

Это не модифицирует («мутирует») переменную; это создание новой переменной с тем же именем и отмена старой. Сравните с мутирующей операцией:

>>> a = [1,2,3]
>>> id(a)
3084599212L
>>> a[1] = 5
>>> a
[1, 5, 3]
>>> id(a)
3084599212L

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

Обратите внимание, что ключи словарей не обязательно должны быть полностью незыблемыми. Неизменной должна быть только ее часть, используемая в качестве ключа; для некоторых видов применения это является важным отличием. Например, можно иметь класс, представляющий пользователя, который сравнивает равенство и хэш по уникальному имени пользователя. Затем можно повесить на класс другие изменяемые данные - «пользователь вошел в систему» и т.д. Поскольку это не влияет ни на равенство, ни на хеш, можно и совершенно справедливо использовать это как ключ в словаре. Это не слишком часто необходимо в Python; Я просто указываю на это, поскольку несколько человек утверждают, что ключи должны быть «незыблемыми», что лишь частично правильно. Я использовал это много раз с картами и наборами C++, хотя.

9
ответ дан 23 November 2019 в 23:28
поделиться
  1. неизменные объекты могут обеспечить существенную оптимизацию; Предположительно, поэтому строки также неизменяются в Java, разработали довольно отдельно, но примерно в то же время, что и питон, и почти все неизменно на действительно функциональных языках.

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

Пример проблемы оптимизации:

$ python -mtimeit '["fee", "fie", "fo", "fum"]'
1000000 loops, best of 3: 0.432 usec per loop
$ python -mtimeit '("fee", "fie", "fo", "fum")'
10000000 loops, best of 3: 0.0563 usec per loop
119
ответ дан 23 November 2019 в 23:28
поделиться
12 --- 2014924-

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

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

Как вы указываете, кортежи неизменяются. Причины, причинами к неизменным типам относится к корзам:

  • Эффективность копирования: вместо копирования неизменного объекта, вы можете псевдоним (связывать переменную к эталону)
  • КПД: когда вы используете копирование Ссылка, вы можете сравнить две переменные, сравнивая местоположение, а не контент
  • Удобрение: вам нужно сохранить максимум одной копии любого неизменного значения
  • Нет необходимости синхронизировать доступ к неизменным объектам в одном режиме
  • Const Правильность: некоторые значения не могут быть разрешены для изменения. Это (для меня) является основной причиной неизменных типов.

Обратите внимание, что конкретная реализация Python может не использовать все вышеперечисленные функции.

Словающие ключевые ключи должны быть неизменными, в противном случае изменяя свойства ключевого объекта, могут недействовать инвариантам базовой структуры данных. Таким образом, кортежи могут потенциально использовать в качестве клавиш. Это следствие корректности Const.

См. Также «, представляющие кортежи », из погружение в Python .

22
ответ дан 23 November 2019 в 23:28
поделиться

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

В последнее время (2.6+) кортежи выросли index() и count() методы

.
15
ответ дан 23 November 2019 в 23:28
поделиться

Как предложил в комментарии Grinibbler, Гвидо был мнение , которое не полностью принято / ценится: «Списки предназначены для однородных данных, кортежи предназначены для гетерогенных данных». Конечно, многие противники интерпретировали это как означающие, что все элементы списка должны быть одного типа.

Мне нравится видеть это по-другому, а не в отличие от Другое Также есть в прошлом:

blue= 0, 0, 255
alist= ["red", "green", blue]

Обратите внимание, что я считаю, что Alist будет однородным, даже если тип (Alist [1])! = Тип ( АЛИСТ [2]).

Если я могу изменить порядок элементов, и у меня не будет проблем в моем коде (кроме предположений, например, он должен быть отсортирован »), то следует использовать список. Если нет (как в кортеже синий выше), то я должен использовать кортеж.

7
ответ дан 23 November 2019 в 23:28
поделиться

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

Прежде чем продолжить, убедитесь, что поведение, продемонстрированное ниже, - это то, что вы ожидаете от Python.

>>> a1 = [1]
>>> a2 = a1
>>> print a2[0]
1
>>> a1[0] = 2
>>> print a2[0]
2

В этом случае содержимое A2 было изменено, хотя только A1 имел назначенное новое значение. Контрастность к следующему:

>>> a1 = (1,)
>>> a2 = a1
>>> print a2[0]
1
>>> a1 = (2,)
>>> print a2[0]
1

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

Почему этот вопрос? Допустим, у вас есть DICK:

>>> t1 = (1,2)
>>> d1 = { t1 : 'three' }
>>> print d1
{(1,2): 'three'}
>>> t1[0] = 0  ## results in a TypeError, as tuples cannot be modified
>>> t1 = (2,3) ## creates a new tuple, does not modify the old one
>>> print d1   ## as seen here, the dict is still intact
{(1,2): 'three'}

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

1
ответ дан 23 November 2019 в 23:28
поделиться

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

.
1
ответ дан 23 November 2019 в 23:28
поделиться

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

Кортежи и списки служат разным целям. Списки хранят однородные данные. Вы можете и должны иметь такой список:

["Bob", "Joe", "John", "Sam"]

Причина, по которой списки используются правильно, заключается в том, что это все однородные типы данных, в частности, имена людей. Но возьмите такой список:

["Billy", "Bob", "Joe", 42]

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

[("Billy", "Bob", "Joe", 42), ("Robert", "", "Smith", 31)]

Непреложность и изменчивость кортежей и списков - не главное различие. Список - это список одних и тех же элементов: файлов, имён, объектов. Кортежи - это группировка различных типов объектов. Они имеют различное использование, и многие кодеры Python используют списки злоупотреблений для того, для чего предназначены кортежи.

Пожалуйста, не надо.


Правка:

Я думаю, что этот пост в блоге объясняет, почему я думаю, что это лучше, чем я думал: http://news.e-scribe.com/397

40
ответ дан 23 November 2019 в 23:28
поделиться

Еще одна область использования - разработка приложений для iPhone (и я считаю, что iPad сейчас также) с помощью MonoTouch.

Что такое MonoTouch?

MonoTouch позволяет разработчикам создавать приложения на базе C # и .NET, которые работают на устройствах iPhone и iPod Touch от Apple, используя преимущества API iPhone и повторно используя как код, так и библиотеки, созданные для .NET, а также существующие навыки.

Примерно так:

MonoTouch - > MonoDeveloper/C # - > напишите приложение iPhone - > скомпилированное в собственный код - > приложение iPhone.

Соответствующие ссылки:

-121--1858958-

TIMEDIFF (endDate, startDate) выводит в формате DateTime, так что для отметки времени и определения (60 * 60)

SELECT (UNIX_TIMESTAMP(TIMEDIFF(endDate, startDate))/(60*60)) AS hours_difference
FROM tasks

Изменить: В качестве альтернативы, TimestampDiff может также предоставить действительное решение более элегантным способом, предоставляя свой пример:

SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');

И ваше решение может быть:

SELECT TIMESTAMPDIFF(HOUR, startDate, endDate) AS hours_different
FROM tasks
-121--1220148-

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

a = [1,1,1]
doWork(a)

вызывающий абонент не имеет гарантии значения a после вызова. Однако

a = (1,1,1)
doWorK(a)

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

6
ответ дан 23 November 2019 в 23:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: