28. Проверить поведение изменения списка внутри кортежа
Условие задачи Проверить поведение кортежа, внутри которого находится изменяемый список: сначала список изменяется через append(), затем выполняется попытка изменить элемент кортежа через оператор +=. Что вывежет код?
data = (['1'], '2')
data[0].append('3')
data[0] += ['4']
print(data)
Спойлеры к решению
Подсказки
- Кортеж
tupleсам по себе неизменяемый. - Но внутри кортежа может лежать изменяемый объект, например список.
data[0].append('3')изменяет список внутри кортежа, это разрешено.data[0] += ['4']сначала изменяет список через__iadd__, а потом пытается записать результат обратно в элемент кортежа.- Запись обратно в кортеж запрещена, поэтому будет
TypeError. - До ошибки список уже успеет измениться.
Решение
data = (['1'], '2')
data[0].append('3')
data[0] += ['4']
print(data)
Код завершится ошибкой:
TypeError: 'tuple' object does not support item assignment
Строка:
print(data)
не выполнится, потому что программа остановится на строке:
data[0] += ['4']
Разбор по шагам:
data = (['1'], '2')
Создаётся кортеж, внутри которого первым элементом лежит список:
(['1'], '2')
Дальше:
data[0].append('3')
Это разрешено, потому что меняется не сам кортеж, а список внутри него. После этой строки состояние будет таким:
(['1', '3'], '2')
Дальше:
data[0] += ['4']
Для списка операция += работает как изменение списка на месте. Список успеет стать таким:
['1', '3', '4']
Но после этого Python пытается присвоить обновлённый список обратно в data[0]. А кортеж нельзя изменять по индексу, поэтому возникает ошибка:
TypeError: 'tuple' object does not support item assignment
Если бы ошибку перехватили через try/except, то можно было бы увидеть, что список внутри кортежа уже изменился:
data = (['1'], '2')
try:
data[0].append('3')
data[0] += ['4']
except TypeError:
print(data)
Результат:
(['1', '3', '4'], '2')
Итог: исходный код ничего не выведет через print(data), потому что до него выполнение не дойдёт. Вместо этого будет ошибка TypeError, но внутренний список уже будет изменён.