Почему глубокая копия списка целых чисел возвращает те же самые целые числа в памяти?
Я понимаю различия между мелкой копией и глубокой копией, как я узнал в классе. Однако следующее не имеет смысла
import copy
a = [1, 2, 3, 4, 5]
b = copy.deepcopy(a)
print(a is b)
print(a[0] is b[0])
----------------------------
~Output~
>False
>True
----------------------------
Не следует print(a[0] is b[0])
оценивать значение False, поскольку объекты и их составляющие элементы воссоздаются в другом месте памяти в глубокой копии? Я просто тестировал это, так как мы обсуждали это в классе, но он, похоже, не работает.
Ответы
Ответ 1
В другом ответе было предложено, что это может быть связано с тем, что Python интернировал объекты для маленьких целых чисел. Хотя это правда, это не то, что вызывает такое поведение.
Давайте посмотрим, что происходит, когда мы используем большие целые числа.
> from copy import deepcopy
> x = 1000
> x is deepcopy(x)
True
Если мы покопаемся в модуле copy
то обнаружим, что вызов deepcopy
с атомарным значением откладывает вызов функции _deepcopy_atomic
.
def _deepcopy_atomic(x, memo):
return x
Так что на самом деле происходит то, что deepcopy
не будет копировать неизменное значение, а только вернет его.
В качестве примера это относится к int
, float
, str
, function
и многим другим.
Ответ 2
Причиной такого поведения является то, что Python оптимизирует небольшие целые числа, поэтому они фактически не находятся в разных ячейках памяти. Проверьте id
1
, они всегда одинаковы:
>>> x = 1
>>> y = 1
>>> id(x)
1353557072
>>> id(y)
1353557072
>>> a = [1, 2, 3, 4, 5]
>>> id(a[0])
1353557072
>>> import copy
>>> b = copy.deepcopy(a)
>>> id(b[0])
1353557072
Ссылка из Целых объектов:
Текущая реализация сохраняет массив целочисленных объектов для всех целых чисел между -5
и 256
, когда вы создаете int в этом диапазоне, вы фактически просто возвращаете ссылку на существующий объект. Поэтому должно быть возможно изменить значение 1
. Я подозреваю, что поведение Python в этом случае undefined.: -)