> Что произойдет при изменении второго элемента списка b, если b = a (Python)

Уровень: middle · Роль: backend · Язык: Python · Категория: Технические вопросы

Компании: JetLend

Стек: Python

> Пример ответа

Короткий ответ

При изменении второго элемента списка b изменится и второй элемент списка a, потому что b = a не создаёт копию, а присваивает обеим переменным ссылку на один и тот же объект списка в памяти. Это поведение называется aliasing - обе переменные указывают на один и тот же изменяемый объект, поэтому любая мутация через одну переменную видна через другую.

Подробное объяснение

В Python переменные - это ссылки на объекты. Когда вы пишете b = a, вы не копируете содержимое списка, а лишь копируете ссылку на тот же объект. Оба имени a и b указывают на один и тот же список в heap-памяти.

Списки - изменяемые (mutable) объекты. Поэтому операция b[1] = ... модифицирует сам объект, на который ссылаются обе переменные. Изменение видно через обе ссылки.

Важно отличать это от:

  • b = a[:] - поверхностная копия (shallow copy), создаёт новый список, но элементы внутри остаются теми же объектами
  • b = a.copy() - то же самое, что и срез
  • b = list(a) - тоже поверхностная копия
  • b = copy.deepcopy(a) - глубокая копия, рекурсивно копирует все вложенные объекты

При поверхностной копии изменение самого списка (добавление, удаление, замена элементов) не затронет оригинал, но изменение вложенных изменяемых объектов (например, если элемент - список) всё равно будет видно в обоих.

На практике

В реальном коде это поведение часто становится источником багов, особенно при передаче списков в функции. Если функция мутирует переданный список, изменения будут видны и в вызывающем коде. Это может быть как желаемым поведением (in-place модификация), так и неожиданным.

Для защиты от нежелательных изменений используйте копирование. Но помните: поверхностная копия защищает только верхний уровень. Для полной изоляции нужен deepcopy.

Также это важно при работе с многопоточностью или при передаче данных между модулями - неявное разделение состояния может привести к трудноотлаживаемым ошибкам.

Пример кода

PYTHON
a = [1, 2, 3]
b = a
b[1] = 99
print(a) # [1, 99, 3]
print(b) # [1, 99, 3]
print(a is b) # True
# Поверхностная копия
c = a[:]
c[0] = 100
print(a) # [1, 99, 3] - не изменился
print(c) # [100, 99, 3]
# Но вложенные объекты всё равно общие
d = [[1, 2], [3, 4]]
e = d[:]
e[0][0] = 100
print(d) # [[100, 2], [3, 4]] - изменился!
print(e) # [[100, 2], [3, 4]]
# Глубокая копия
import copy
f = copy.deepcopy(d)
f[0][0] = 500
print(d) # [[100, 2], [3, 4]] - не изменился
print(f) # [[500, 2], [3, 4]]

Как отвечать на собеседовании

Начните с прямого ответа: "Список a тоже изменится". Затем объясните механизм: присваивание копирует ссылку, а не объект. Упомяните, что списки - изменяемые объекты, и мутация через одну ссылку видна через другую.

Покажите понимание различий между присваиванием, поверхностной и глубокой копией. Приведите пример с вложенными списками, чтобы продемонстрировать, что поверхностная копия не защищает от изменений вложенных объектов.

Если спросят про неизменяемые типы (например, кортежи), отметьте, что там такая проблема не возникает - попытка изменить кортеж вызовет ошибку, а не изменит оригинал.

Что проверяет интервьюер

Интервьюер проверяет:

  • понимание модели данных Python: переменные как ссылки, изменяемые и неизменяемые типы
  • знание механизма присваивания и копирования
  • умение предсказывать поведение кода с aliasing
  • осознание практических последствий для production-кода

Это базовый вопрос, но он выявляет, насколько кандидат понимает внутреннее устройство языка, а не просто знает синтаксис. Хороший ответ показывает системное мышление и опыт отладки подобных проблем.

Типичные ошибки

  • Утверждение, что b = a создаёт копию - это грубая ошибка
  • Путаница между изменением самого списка и изменением элементов внутри него
  • Утверждение, что срез a[:] полностью изолирует данные - неверно для вложенных объектов
  • Игнорирование разницы между is и == - здесь важно именно is, так как объект один
  • Непонимание, что передача списка в функцию и мутация внутри неё также изменяет оригинал
  • Ожидание, что неизменяемые типы ведут себя так же - они не позволяют мутацию, поэтому проблема не возникает

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью