Я прочитал несколько руководств по python (например, «Dive Into Python») и справочник по языку на Python.org - я не понимаю, зачем этому языку нужны кортежи.
Кортежи не имеют методов по сравнению со списком или набором, и если я должен преобразовать кортеж в набор или список, чтобы иметь возможность их сортировать, какой смысл использовать кортеж в первую очередь?
Неизменяемость?
Почему кого-то волнует, находится ли переменная в другом месте в памяти, чем когда она была изначально выделена? Кажется, что этому вопросу неизменности в Python уделяется чрезмерное внимание.
В C / C ++, если я выделяю указатель и указываю на некоторую допустимую память, мне все равно, где находится адрес, если он не равен нулю, прежде чем я его использую.
Всякий раз, когда я ссылаюсь на эту переменную, мне не нужно знать, указывает ли указатель на исходный адрес или нет. Я просто проверяю значение null и использую его (или нет).
В Python, когда я выделяю строку (или кортеж), назначаю ее x, а затем изменяю строку, почему меня волнует, является ли это исходным объектом? Пока переменная указывает на мои данные, это все, что имеет значение.
>>> x='hello'
>>> id(x)
1234567
>>> x='good bye'
>>> id(x)
5432167
x
по-прежнему ссылается на данные, которые я хочу, почему кому-то нужно заботиться о том, такой же или другой идентификатор?
Ответы:
неизменяемые объекты могут допускать существенную оптимизацию; По-видимому, именно поэтому строки также неизменны в Java, разрабатываются совершенно отдельно, но примерно в то же время, что и Python, и практически все неизменяемо в действительно функциональных языках.
в частности, в 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
источник
random
звонки (попробуйте сделать именно это, вы увидите!), Так что это не очень важно. Попробуйте,python -mtimeit -s "x=23" "[x,x]"
и вы увидите более значимое ускорение в 2-3 раза для построения кортежа по сравнению с построением списка.Ни один из приведенных выше ответов не указывает на реальную проблему кортежей и списков, которую многие новички в Python, похоже, не полностью понимают.
Кортежи и списки служат разным целям. Списки хранят однородные данные. У вас может и должен быть такой список:
["Bob", "Joe", "John", "Sam"]
Причина правильного использования списков заключается в том, что это все однородные типы данных, в частности, имена людей. Но возьмите такой список:
["Billy", "Bob", "Joe", 42]
В этом списке указаны полное имя одного человека и его возраст. Это не один из типов данных. Правильный способ хранения этой информации - либо в кортеже, либо в объекте. Допустим, у нас есть несколько:
[("Billy", "Bob", "Joe", 42), ("Robert", "", "Smith", 31)]
Неизменяемость и изменчивость кортежей и списков - не главное различие. Список - это список однотипных элементов: файлов, имен, объектов. Кортежи - это группа объектов разных типов. Они используются по-разному, и многие программисты Python злоупотребляют списками, для которых предназначены кортежи.
Пожалуйста, не надо.
Редактировать:
Я думаю, это сообщение в блоге объясняет, почему я считаю это лучше, чем я: http://news.e-scribe.com/397
источник
В данном конкретном случае, вероятно, нет смысла. Это не проблема, потому что это не тот случай, когда вы бы рассматривали возможность использования кортежа.
Как вы отметили, кортежи неизменяемы. Причины наличия неизменяемых типов применимы к кортежам:
Обратите внимание, что конкретная реализация Python может не использовать все вышеперечисленные функции.
Ключи словаря должны быть неизменными, в противном случае изменение свойств ключевого объекта может сделать недействительными инварианты базовой структуры данных. Таким образом, кортежи потенциально могут использоваться как ключи. Это следствие правильности const.
См. Также « Введение в кортежи » из книги « Dive Into Python» .
источник
==
это реализовано на уровне платформы.(1,2,3) == (1,2,3)
. Это больше вопрос интернирования.Иногда нам нравится использовать объекты как ключи словаря
Как бы то ни было, недавно кортежи (2.6+) выросли,
index()
аcount()
методыисточник
Я всегда считал, что наличие двух совершенно разных типов для одной и той же базовой структуры данных (массивов) неудобно, но не представляет реальной проблемы на практике. (У каждого языка есть свои недостатки, включая 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 ++.
источник
Как сказал gnibbler в комментарии, у Гвидо было мнение , которое не полностью принято / не оценено: «списки предназначены для однородных данных, кортежи - для разнородных данных». Конечно, многие противники истолковали это как означающее, что все элементы списка должны быть одного типа.
Мне нравится видеть это по-другому, в отличие от других, которые были в прошлом:
blue= 0, 0, 255 alist= ["red", "green", blue]
Обратите внимание, что я считаю alist однородным, даже если type (alist [1])! = Type (alist [2]).
Если я могу изменить порядок элементов, и у меня не будет проблем в моем коде (кроме предположений, например, «он должен быть отсортирован»), тогда следует использовать список. Если нет (как в кортеже
blue
выше), то я должен использовать кортеж.источник
Они важны, поскольку гарантируют вызывающей стороне, что передаваемый объект не будет изменен. Если вы сделаете это:
a = [1,1,1] doWork(a)
У вызывающего абонента нет гарантии значения a после вызова. Однако,
a = (1,1,1) doWorK(a)
Теперь вы, как вызывающий или читающий этот код, знаете, что a - то же самое. В этом сценарии вы всегда можете сделать копию списка и передать ее, но теперь вы тратите циклы вместо использования языковой конструкции, которая имеет более семантический смысл.
источник
вы можете увидеть здесь обсуждение этого
источник
Ваш вопрос (и последующие комментарии) сосредоточены на том, изменяется ли 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
В последнем случае мы заменили весь список, а не обновили его содержимое. Для неизменяемых типов, таких как кортежи, это единственное допустимое поведение.
Почему это важно? Допустим, у вас есть диктант:
>>> 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'}
Используя кортеж, словарь безопасен от того, чтобы его ключи были изменены «из-под него» на элементы, хеш-значения которых имеют другое значение. Это очень важно для эффективной реализации.
источник