Чем кортеж отличается от списка? Можно ли менять элементы кортежа?
Только начал и не догоняю, зачем вообще нужны кортежи, если есть списки. Пробую поменять элемент:
t = (1, 2, 3)
t[0] = 99 # TypeError
Почему нельзя? И когда брать (), а когда []? Слышал, что кортеж можно положить ключом в словарь, а список нельзя — это правда?
2 ответа
Главное отличие одно: список изменяемый (mutable), кортеж — нет (immutable). Из этого вытекает всё остальное.
lst = [1, 2, 3]
lst[0] = 99 # ок, список можно менять
lst.append(4) # ок
t = (1, 2, 3)
t[0] = 99 # TypeError: 'tuple' object does not support item assignment
У кортежа физически нет методов append, remove, присваивания по индексу — он создаётся один раз и дальше только читается.
Когда что брать:
- Список — когда набор будет меняться: накапливаешь, сортируешь, удаляешь.
- Кортеж — когда это фиксированная запись, и менять её не предполагается: координата
(x, y), RGB-цвет(255, 0, 0), строка из БД. Неизменяемость тут страховка: случайно не перезапишешь.
Про ключ словаря — да, правда. Ключ должен быть хешируемым, а хешируемость требует неизменяемости. Список менять можно, значит его хеш «поплыл бы», поэтому Python его как ключ не пускает:
point_names = {(0, 0): 'origin', (1, 2): 'A'}
print(point_names[(1, 2)]) # A
bad = {[0, 0]: 'x'} # TypeError: unhashable type: 'list'
Это же даёт кортежам место в set и возможность быть составным ключом.
Бонус — распаковка, кортежи для неё созданы:
x, y = (10, 20)
a, b = b, a # обмен значениями — справа кортеж
Если коротко: меняешь данные — [], фиксируешь — ().
Важный подвох, на котором спотыкаются почти все. Неизменяемость кортежа — про сам кортеж, а не про то, что внутри. Если положить туда список, его содержимое поменять можно:
t = (1, [2, 3])
t[1].append(4)
print(t) # (1, [2, 3, 4]) — кортеж «изменился»
t[1] = [9] # а вот это всё ещё TypeError
Кортеж держит ссылки фиксированными, но если ссылка ведёт на изменяемый объект — его внутренности живут своей жизнью. Из-за этого, кстати, такой кортеж становится нехешируемым и ключом словаря уже не станет.