目录
1 深浅拷贝理解
浅拷贝,指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。
深拷贝,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。
浅拷贝得到的新对象与原对象内部的子对象是相同的,子对象具有相同的数据与地址,修改新对象的子对象中的不可变数据类型变量时,原对象的变量值不会改变,修改新对象的子对象中的可变数据类型变量时,原对象的值也会跟着改变。深拷贝之后的对象与原来的对象没有关系,只是存放的数据相同,可变数据类型的地址不同。
2 浅拷贝
2.1 使用copy. copy()函数浅拷贝
import copy
list1 = [1, 2, [1, 2, 3]]
list2 = copy.copy(list1)
print(list2 == list1) # True list2与list1中的数据相同
print(list2 is list1) # False list2与list1是不同的对象
print(id(list1) == id(list2)) # False list2与list1内存地址不同
对新对象list2中的不可变数据进行赋值操作(分配了新的内存空间),此时list1中对应的位置不会改变
list2[1] = 100
print(list1, list2)
# [1, 2, [1, 2, 3]] [1, 100, [1, 2, 3]]
print(id(list1[0]), id(list2[0])) # 1798725265712 1798725265712
print(id(list1[1]), id(list2[1])) # 1798725265744 1798725457360
若对新对象list2中的可变数据进行修改操作,list1中对应自变量会改变
ist2[2].append(100)
print(list1, list2) # [1, 2, [1, 2, 3, 100]] [1, 100, [1, 2, 3, 100]]
2.2 使用数据类型构造器浅拷贝
list1 = [1, 2, 3, [1, 2, 3]]
list2 = list(list1)
print(list1, list2) # [1, 2, 3, [1, 2, 3]] [1, 2, 3, [1, 2, 3]]
# 不可变数据
list2[1] = 100
print(list1, list2) # [1, 2, 3, [1, 2, 3]] [1, 100, 3, [1, 2, 3]]
# 可变数据
list2[2].append(5)
print(list1, list2) # [1, 2, 3, [1, 2, 3, 5]] [1, 100, 3, [1, 2, 3, 5]]
2.3 列表使用切片进行浅拷贝
list1 = [1, 2, 3, [1, 2, 3]]
list2 = list1[1:]
print(list1, list2) # [1, 2, 3, [1, 2, 3]] [2, 3, [1, 2, 3]]
# 不可变数据
list2[1] = 100
print(list1, list2) # [1, 2, 3, [1, 2, 3]] [2, 100, [1, 2, 3]]
# 可变数据
list2[2].append(5)
print(list1, list2) # [1, 2, 3, [1, 2, 3, 5]] [2, 100, [1, 2, 3, 5]]
2.4 赋值操作与浅拷贝的区别
赋值是对原对象的引用,相当于给对象起了个别名,而浅拷贝是把原对象的引用复制给新对象。赋值得到的新对象,当改变其变量值时,不论是可变还是不可变数据类型的值,原对象的值也会跟着改变。
import copy
list1 = [1, 2, [1, 2, 3]]
list2 = list1
print(list2 == list1) # True list2与list1中的数据相同
print(list2 is list1) # True list2与list1是相同的对象
print(id(list1) == id(list2)) # True list2与list1内存地址相同
list2[1] = 100
print(list1, list2) # [1, 100, [1, 2, 3]] [1, 100, [1, 2, 3]]
print(id(list1[0]), id(list2[0])) # 2433504143664 2433504143664
print(id(list1[1]), id(list2[1])) # 2433504335312 2433504335312
list1[2].append(100)
print(list1, list2) # [1, 100, [1, 2, 3, 100]] [1, 100, [1, 2, 3, 100]]
3 深拷贝
在python中,浅拷贝使用copy. deepcopy()函数。
import copy
list1 = [1, 2, [1, 2, 3]]
list2 = copy.deepcopy(list1)
print(list2 == list1) # True list2与list1中的数据相同
print(list2 is list1) # False list2与list1是不同的对象
print(id(list1) == id(list2)) # False list2与list1内存地址不同
print(id(list1), id(list2)) # 2433627089600 2433627099968
# 不可变数据
list2[1] = 100
print(list1, list2) # [1, 2, [1, 2, 3]] [1, 100, [1, 2, 3]]
print(id(list1[0]), id(list2[0])) # 2433504143664 2433504143664
print(id(list1[1]), id(list2[1])) # 2433504143696 2433504335312
print(id(list1[2]), id(list2[2])) # 2433559239616 2433633751488 可变子对象具有不同的地址
# 可变数据
list2[2].append(100)
print(list1, list2) # [1, 2, [1, 2, 3]] [1, 100, [1, 2, 3, 100]]
print(id(list1[0]), id(list2[0])) # 2433504143664 2433504143664 对于不可变数据类型变量,变量值相同,地址相同
print(id(list1[1]), id(list2[1])) # 2433504143696 2433504335312
print(id(list1[2]), id(list2[2])) # 2433559239616 2433633751488 可变子对象的值更改后,地址不变
深拷贝后的两个对象是完全不同的对象,改变新对象中的任意变量不会对原对象造成影响。对于可变数据类型的子对象,深拷贝之后,子对象地址发生改变,但浅拷贝时不变。
4 numpy的深浅拷贝
4.1 numpy的浅拷贝
numpy中使用赋值(=)操作或者view()函数进行浅拷贝操作。
import numpy as np
a = np.array([1, 2, 3, 4])
b = a.view()
c = a
b[0] = 100
print(a, b, c) # [100 2 3 4] [100 2 3 4] [100 2 3 4]
4.2 numpy的深拷贝
numpy中使用copy()函数进行浅拷贝操作。
import numpy as np
a = np.array([1, 2, 3, 4])
b = a.copy()
b[0] = 100
print(a, b) # [1 2 3 4] [100 2 3 4]