Содержание
- Краткое резюме 📌
- Объекты и переменные в Python: основы
- Пример со списком: почему переменные ссылаются на один объект
- Локальные переменные и функция
locals()
- Копирование объектов: поверхностное и глубокое
- Выводы и особенности
Краткое резюме 📌
- В Python всё является объектом, а переменные хранят не сами объекты, а ссылки на них.
- Присваивание переменно́й фактически копирует ссылку, а не сам объект.
- Изменение объекта через одну переменную отражается при доступе через другую, если обе указывают на один объект.
- Чтобы получить копию объекта, можно использовать поверхностное копирование (через конструктор или
copy.copy()
), которое создаёт новый объект, но ссылки внутри копии всё равно указывают на оригинальные вложенные объекты. - Для правильного копирования вложенных структур используется глубокое копирование (
copy.deepcopy()
), которое рекурсивно дублирует все вложенные объекты. - В редких случаях даже глубокое копирование может оказаться недостаточным, и такие ситуации требуют индивидуального подхода.
Объекты и переменные в Python: основы
Автор начинает с простого примера, чтобы показать, что происходит при создании объекта и переменных в Python.
- При исполнении кода интерпретатор сначала создаёт объект в памяти, например,
set
. - Затем создаётся переменная, в пространстве имён которой хранится ссылка на этот объект.
- При присваивании второй переменной той же ссылки происходит ситуация, когда обе переменные указывают на один и тот же объект.
«Переменные хранят ссылки на объекты, и везде в программах на Python объекты передаются по ссылкам.»
Пример со списком: почему переменные ссылаются на один объект
Рассмотрим список:
a = [1, 2, 3]
b = a
b[0] = 4
print(a) # [4, 2, 3]
print(b) # [4, 2, 3]
Что происходит:
- Создаются объекты
1
,2
,3
. - Создаётся объект
list
, со ссылками на эти числа. 3.Переменнаяa
ссылается на этот список. - Переменная
b
получает копию ссылки на тот же самый список. - Изменяя элемент списка через
b
, мы изменяем один и тот же объект, который доступен и черезa
.
Локальные переменные и функция locals()
Если нужно увидеть, какие переменные существуют и на что они ссылаются, можно использовать locals()
, которая возвращает словарь с текущими именами и объектами.
Копирование объектов: поверхностное и глубокое
Поверхностное копирование (shallow copy)
Пример:
a = [1, 2, 3]
b = list(a) # или b = copy.copy(a)
b[0] = 4
print(a) # [1, 2, 3]
print(b) # [4, 2, 3]
- В памяти создаётся новый список
b
, но элементы внутри всё ещё ссылаются на те же объекты1
,2
,3
. - Изменение элемента списка
b
не влияет наa
, если сама ссылка изменена. - Однако, если элементы — вложенные объекты (например, вложенные списки), поверхностное копирование не создаст отдельные вложенные объекты.
Пример с вложенными списками:
a = [0, [2, 3]]
b = list(a)
b[1][0] = 4
print(a) # [0, [4, 3]]
print(b) # [0, [4, 3]]
Здесь и a
, и b
ссылаются на один и тот же вложенный список. Изменение через b
отражается в a
.
«Поверхностное копирование создаёт новый контейнер, но внутри элементы — это ссылки на исходные объекты.»
Глубокое копирование (copy.deepcopy
)
Чтобы создать полностью независимую копию объекта вместе со всеми вложенными структурами, используют глубокое копирование:
import copy
a = [0, [2, 3]]
b = copy.deepcopy(a)
b[1][0] = 4
print(a) # [0, [2, 3]]
print(b) # [0, [4, 3]]
- Создаются отдельные объекты не только для внешнего списка, но и для всех вложенных элементов.
- Изменения в
b
не затрагиваютa
.
Выводы и особенности
- Успех многократно зависит от понимания, что переменные — это ссылки.
- Неправильный способ копирования может привести к неожиданным побочным эффектам из-за общих ссылок.
- Глубокое копирование — мощный инструмент, но не всегда гарантирует совершенство. Иногда могут быть сложные структуры, для которых нужно писать собственную логику копирования.
«Иногда даже
deepcopy
оказывается недостаточно глубоким — подобные случаи полезно проработать самостоятельно.»
✨ Понимание работы с объектами, ссылками и копированием — фундаментальный шаг к грамотному программированию на Python.