Какие типы в Python изменяемые, а какие нет, и почему это важно?
Короткий ответ
- Неизменяемые: int, float, str, tuple, frozenset, bytes
- Изменяемые: list, dict, set, bytearray и свои классы
- Неизменяемый объект нельзя поменять, создаётся новый
- Изменяемые объекты передаются по ссылке — правки видны везде
- Ключами dict могут быть только хешируемые объекты
- Изменяемый аргумент по умолчанию — классическая ловушка
Изменяемость определяет, меняется объект на месте или создаётся новый, и это влияет на ссылки, хеширование и побочные эффекты.
Как сказать вслух
пример ответаНеизменяемые типы — это числа, строки, кортежи: любое «изменение» создаёт новый объект. Списки, словари и множества меняются на месте, и если две переменные ссылаются на один список, правка видна через обе. Поэтому изменяемые объекты нельзя использовать как ключи словаря и как значения по умолчанию в аргументах функций.
Подробный ответ
Основной ответ
В Python переменная — это ссылка на объект. Неизменяемые типы (int, float, str, tuple, frozenset, bytes) нельзя поменять после создания: операции вроде конкатенации строк возвращают новый объект. Изменяемые (list, dict, set, bytearray, большинство пользовательских классов) меняются на месте, поэтому все ссылки на объект «видят» изменение. Отсюда следствия: изменяемые объекты не хешируются и не годятся в ключи dict и элементы set; передача списка в функцию позволяет функции изменить его у вызывающего; кортеж неизменяем сам, но может содержать изменяемые элементы.
Ключевые моменты
- Семантика ссылок. Присваивание не копирует объект, а создаёт ещё одну ссылку. b = a для списка значит, что это один и тот же объект.
- Хешируемость. Ключи dict и элементы set должны быть хешируемыми, то есть практически неизменяемыми. list в ключ не положить, tuple — можно.
- Строки и эффективность. Конкатенация строк в цикле создаёт новые объекты на каждой итерации; лучше собрать список и сделать ''.join().
- Кортеж не гарантирует глубокой неизменяемости. Кортеж со списком внутри неизменяем только на верхнем уровне: сам список менять можно.
Практический контекст
На практике это всплывает в багах с «общим состоянием»: один список попал в два места и изменился в обоих, или dict передали в функцию, а она его мутировала. Интервьюер проверяет, понимает ли кандидат модель памяти Python, а не просто перечисляет типы. Хороший ход — упомянуть id(), is и ловушку с изменяемым значением по умолчанию.
Пример кода
a = [1, 2]
b = a # та же ссылка
b.append(3)
print(a) # [1, 2, 3]
t = (1, [2, 3])
t[1].append(4) # кортеж «неизменяем», но список внутри — нет
print(t) # (1, [2, 3, 4])Частые ошибки
- Говорят «переменная хранит значение», не понимая, что это ссылка на объект
- Считают кортеж полностью неизменяемым, забывая про изменяемые элементы внутри
- Путают == (равенство значений) и is (идентичность объектов)