В чем разница между списками и кортежами в Python?

что более эффективно? Каково типичное использование каждого?

4 ответов


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

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

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

return fee, fie, foo, fum

т. е. верните кортеж с четырьмя рассматриваемыми элементами, а не

return [fee, fie, foo, fum]

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

полезный вариант tuple является его подтипом коллекций.namedtuple (требуется Python 2.6 или лучше), который позволяет получить доступ к элементам по имени (с синтаксисом атрибутов), а также по индексу (обычным способом). Например, с помощью import collections в верхней части модуля, выше return заявление может становиться...

freturn = collections.namedtuple('freturn', 'fee fie foo fum')

def f():
  ...
return freturn(fee, fie, foo, fum)

теперь, вызывающий f() может использовать его возвращаемое значение в качестве кортежа, как и раньше, но получит хорошие альтернативы, такие как...:

r = f()
print r.fie

вместо того, чтобы менее сразу ясно и читабельно

print r[1]

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

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


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

читать этой.


списки изменчивы (могут быть изменены), кортежи неизменяемы. Типичное использование: это звучит довольно банально, но вы используете списки, когда вам нужно изменить значения. Кортежи, как правило, немного эффективнее из-за их неизменности (если вы не используете их как списки и не дублируете их много...)


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

<pre>
Container   Notation     Index [n:m]   Mutable   Hashable
=========   ==========   ===========   =======   ========
String      ' ' or " "    position     Immutable    Yes
Range       range(,,)     position     Immutable    Yes
Tuple       (,)           position     Immutable    Yes
List        [,]           position     Yes          No
Set         {,}           No           Yes          No
Dict        {k:v,k:v}     by key       Yes          No
</pre>

поиск быстрее для set и dict, потому что они хэшируются вместо последовательности и, следовательно, не зависят от размера. Кортеж и список одинаковы, за исключением того, что кортеж неизменяем с меньшим количеством методов, чем список, поэтому он не поддерживает назначение элемента для изменения его содержимого. Но два кортежа могут быть объединены для достижения "добавить" функциональность, т. е. t1 += t2.

поскольку только неизменяемые типы последовательностей поддерживают hash (), list, set и dict не могут использоваться в качестве ключа dict. Это можно легко увидеть ниже, где " a " - последовательность dict, которая содержит гетеро неизменяемые ключевые типы int, float, str, range и tuple:

>>> a
{range(2, 5, 2): 'range', 3: 15, 4.5: 16, 'llmjxm': 'c', -555: 666, -4.5: -25, (5, 6, 7): 'blue', 'abc3': 215, (1, 2, 3): 'red'}
>>> for item in a.keys():
...     print(item, '\t\t==>>', a[item])
... 
range(2, 5, 2)      ==>> range
3       ==>> 15
4.5         ==>> 16
llmjxm      ==>> c
-555        ==>> 666
-4.5        ==>> -25
(5, 6, 7)       ==>> blue
abc3        ==>> 215
(1, 2, 3)       ==>> red
>>> 

тогда как ключ изменяемого типа приведет к TypeError:

>>> a[{5}] = 56
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> a[[5]] = 56
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> a[{5:6}] = 56
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> a[-555] = 666
>>> 

смотрите link1 и и link2 для получения более подробной информации.