Существует три типа использования копирования объектов в Python: присваивание, поверхностное копирование и глубокое копирование. Они оба разные и связанные.Я недавно столкнулся с проблемой такого типа и изучаю ее.
1. Задание
В python назначение объекта — это простая ссылка на объект, что отличается от C++. следующее:
a = [1,2,3,"hello",["python","C++"]]
b = a
print a==b #True
В этом случае b и a — одно и то же, они указывают на один и тот же фрагмент памяти, b — это просто псевдоним a, ссылка. Мы можем использовать, чтобы судить о том, являются ли a и b одинаковыми, и возвращать True, указывая, что они имеют одинаковый адрес и одинаковое содержимое.
Операции присваивания (включая объекты в качестве параметров, возвращаемые значения) не открывают новое пространство памяти, а просто копируют ссылку на новый объект. То есть нет никаких других накладных расходов памяти, кроме имени b.
Изменение a повлияет на b, точно так же изменение b повлияет на a.
a = [1,2,3,"hello",["python","C++"]]
b = a
b.append("ADD")
print("a=",a,"b=",b)
#a=[1, 2, 3, 'hello', ['python', 'C++'], 'ADD'] b=[1, 2, 3, 'hello', ['python', 'C++'], 'ADD']
2. Поверхностное копирование
Неглубокая копия создает новый объект, содержимое которого является ссылкой на исходный объект.
Существует три формы неглубокого копирования: операция среза, фабричная функция, функция копирования в модуле копирования.
Например, для приведенного выше a:
1. Операция нарезки: b = a[:] или b = [каждый для каждого в a]
2. Заводская функция: b = list(a)
3. Функция копирования: b = copy.copy(a)
b, сгенерированный поверхностной копией, больше не является a. Вы можете использовать is, чтобы обнаружить, что они не являются одним и тем же объектом. Используйте id, чтобы проверить и обнаружить, что они не указывают на один и тот же участок памяти. Но когда мы используем id(x) для x в a и id(x) для x в b, мы видим, что адреса элементов, содержащихся в обоих, одинаковы.
В этом случае a и b — разные объекты, и изменение b теоретически не повлияет на a. Например, b.append([4,5]).
a = [1,2,3,"hello",["python","C++"]]
b = a[:]
b.append("ADD")
print "a",a,"b",b
#a [1, 2, 3, 'hello', ['python', 'C++']] b [1, 2, 3, 'hello', ['python', 'C++'], 'ADD']
Но следует отметить, что причина, по которой мелкая копия называется мелкой копией, заключается в том, что она копирует только один уровень, а в нем есть вложенный список.Если мы его изменим, ситуация будет другой.
а[4].присоединить("С"). Посмотрите на b, и вы увидите, что b тоже изменилось. Это потому, что вы изменяете вложенный список. Изменение внешнего элемента изменит его ссылки, заставив их указывать на другие места, изменив элементы во вложенном списке, адрес списка не изменится, и все они будут указывать на одно и то же место.
3. Глубокое копирование
Существует только одна форма глубокого копирования — функция глубокого копирования в модуле копирования.
В соответствии с мелкой копией, глубокая копия копирует все элементы объекта, включая многоуровневые вложенные элементы. Следовательно, его время и объем накладных расходов высоки.
Аналогично для la, если используется b = copy.deepcopy(a), то изменение b не повлияет на a. Даже если вложенный список имеет более глубокий уровень, он не будет иметь никакого эффекта, потому что глубоко скопированный объект — это просто совершенно новый объект, который больше не имеет никакого отношения к исходному объекту.
В-четвертых, предупреждение об операции копирования
1. Для типов, не являющихся контейнерами, таких как числа, символы и другие «атомарные» типы, копирование не выполняется. То, что получается, является ссылкой на исходный объект.
2. Если значение переменной кортежа содержит объект атомарного типа, даже если используется глубокая копия, может быть получена только поверхностная копия.