Является ли список (list) изменяемым типом данных в Python
Что проверяют
Вопрос базовый, поэтому смотрят не на «да», а на следствия: понимаете ли вы разницу между изменением объекта и переприсваиванием имени и переносите ли это на работу с данными, где мутация на месте главный источник неповторяемых результатов.
Как отвечать
Да, список изменяемый. append, присваивание по индексу или срезу, sort меняют сам объект, id() при этом остаётся прежним, и все имена, ссылающиеся на список, видят новое содержимое.
Отсюда следствия, которые и хотят услышать.
Изменяемость связана с хешируемостью: список нельзя положить в set или взять ключом словаря, кортеж можно. Поэтому составной ключ в группировках собирают кортежем.
Копия делается явно: list(x) даёт поверхностную копию, вложенные списки останутся общими, для честной копии нужен copy.deepcopy.
Изменяемое значение по умолчанию создаётся один раз при определении функции и живёт между вызовами:
def collect(item, acc=[]): # ловушка: acc общий для всех вызовов
acc.append(item)
return acc
def collect(item, acc=None):
acc = [] if acc is None else accДля данных важнее всего поведение срезов. Срез списка возвращает копию, срез массива NumPy возвращает представление на ту же память, и запись в него меняет исходный массив. Из-за этого функция, которая «просто нормализует колонку», незаметно портит входной набор, а шаг конвейера перестаёт быть воспроизводимым при повторном запуске.
Где спотыкаются
Проверяют изменяемость через is после конкатенации. Выражение x = x + [1] создаёт новый объект, а x += [1] мутирует существующий, и на этой паре легко сделать противоположный вывод.
Считают кортеж гарантией неизменности содержимого. Кортеж фиксирует состав ссылок, но список внутри него правится по-прежнему, и ключом словаря такой кортеж уже не станет.
Пишут функции признаков, которые меняют переданный объект на месте и ничего не возвращают. При перезапуске ячейки или перестановке шагов результат отличается, а причину приходится искать в данных, а не в коде.