Это сводится к тому, создаете ли вы новые объекты или нет. Оказывается, подходы с 1 по 3 не создают новые объекты, вот почему.
Подход 1 и 3: ❌
Хотя они выглядят по-разному, эти два подхода одинаковы. При вызове copy.deepcopy
для целого числа (или любого неизменяемого встроенного типа) модуль copy
использует следующий метод.
def _deepcopy_atomic(x, memo):
return x
Поэтому, когда вы копируете целое число глубже, возвращается тот же самый объект . Точно так же, глубокое копирование списка целых чисел фактически возвращает поверхностную копию.
from copy import deepcopy
l = [1000]
print(l[0] is deepcopy(l)[0]) # True
Подход 2: 101
Делая [x for x in a]
, вы тривиально создаете новый список с точно такими же объектами. Вот проверка здравомыслия.
l1 = [1000]
l2 = [x for x in l1]
print(l1[0] is l2[0]) # True
Подход 4: ✅
Теперь этот подход фактически создает новый объект для целых чисел больше 256.
x = 1000
print(x is x + 0) # False
Последнее слово
Хотя последний подход является единственным, который фактически создает новый объект, я не смог найти ничего в документе, утверждающем, что это свойство языка. Так что имейте в виду, что это может зависеть от реализации и что весьма вероятно, что возникнет интерпретация, которая оптимизирует x + 0
, чтобы всегда возвращать один и тот же объект.