Ответ
В Python переменные — это имена (names), которые ссылаются на объекты (objects) в памяти. Присваивание (=) связывает имя с объектом, а не копирует сам объект. Это называется передачей по ссылке на объект.
Ключевое правило: «Объекты не копируются при присваивании».
Пример 1: Изменяемые объекты (списки, словари, множества)
a = [1, 2, 3] # Создается список, `a` ссылается на него
b = a # `b` теперь ссылается на ТОТ ЖЕ объект в памяти
a.append(4) # Изменяем объект через ссылку `a`
print(a) # [1, 2, 3, 4]
print(b) # [1, 2, 3, 4] - `b` «видит» изменения, так как ссылается на тот же объект
print(a is b) # True - это один и тот же объект (проверка по id)
Пример 2: Неизменяемые объекты (числа, строки, кортежи)
x = 10 # `x` ссылается на объект `int` со значением 10
y = x # `y` ссылается на тот же объект `10`
x = x + 5 # Операция создает НОВЫЙ объект `int(15)`. `x` теперь ссылается на него.
print(x) # 15
print(y) # 10 - `y` продолжает ссылаться на старый объект `10`
С неизменяемыми объектами безопасно, так как их нельзя изменить «на месте».
Создание независимых копий:
- Поверхностное копирование (
copy()): Создает новый контейнер, но вкладывает в него ссылки на те же вложенные объекты.import copy list1 = [1, [2, 3]] list2 = copy.copy(list1) # Поверхностная копия list1[0] = 100 # Изменяется только list1 list1[1].append(4) # Изменяется вложенный список, что затронет list2! print(list1) # [100, [2, 3, 4]] print(list2) # [1, [2, 3, 4]] # Вложенный список общий! - Глубокое копирование (
deepcopy()): Рекурсивно создает новые копии всех объектов, включая вложенные.list3 = copy.deepcopy(list1) # Глубокая копия list1[1].append(5) print(list1) # [100, [2, 3, 4, 5]] print(list3) # [100, [2, 3, 4]] # Полностью независимая копия
Практический вывод: При передаче изменяемых объектов в функции или при присваивании помните, что вы работаете с исходным объектом. Если нужна независимая копия — используйте copy или deepcopy.