Что такое глубокое и поверхностное копирование в Python
Что проверяют
Понимаете ли вы, что переменная хранит ссылку, и умеете ли предсказать, где правка копии заденет оригинал. Тема сквозная: во фронтенде те же грабли ловят на состоянии, поэтому формулировка про Python проверяет понимание модели, а не знание одной библиотеки.
Как отвечать
Поверхностная копия создаёт новый контейнер, но кладёт в него те же ссылки на вложенные объекты. Глубокая обходит структуру рекурсивно и создаёт новые объекты на всех уровнях. В Python это copy.copy и copy.deepcopy; поверхностными оказываются также срез списка, dict.copy и вызов конструктора вроде list(...).
import copy
a = {"tags": ["new"]}
b = copy.copy(a)
b["tags"].append("old") # список внутри a тоже изменился
c = copy.deepcopy(a)Стоит добавить, что deepcopy ведёт словарь уже скопированных объектов, поэтому переживает циклические ссылки и не дублирует общий подобъект дважды, а поведение настраивается методами __copy__ и __deepcopy__.
Параллель с JavaScript уместна и показывает, что тема понята: разворачивание объекта и Object.assign поверхностные, structuredClone делает глубокую копию и справляется с циклами, а привычный приём через сериализацию в JSON теряет функции и даты и падает на циклических ссылках.
Где спотыкаются
Считают, что копия всегда нужна глубокая. Она дорога и часто бессмысленна: соединение с базой, открытый файл или блокировку копировать нечего, а в интерфейсе достаточно пересобрать путь до изменяемого узла, оставив остальное общим.
Ловят общий вложенный объект. Список списков, собранный умножением, содержит одну и ту же ссылку несколько раз, и запись в один элемент видна во всех. Тот же корень у изменяемого значения по умолчанию в аргументе функции: оно создаётся один раз на всю жизнь функции.
Путают копирование с равенством и неизменяемостью. Копия равна оригиналу по значению, но это другой объект, и проверка на тождество даст ложь. А кортеж или замороженная структура защищают только верхний уровень: вложенный список внутри них остаётся изменяемым.