浅拷贝:b = a.copy() 浅拷贝的时候,修改b,如果只修改第一层的内容,只会影响到s3对s没有影响,如果对s3的第二层修改之后,s也会被修改
原因: 因为s[0]这个列表是另一个列表类型,它有自己的内存地址,s3和s的第一个元素都是指向这个【1,2】内存地址的 ,所以,当修改了s3之后,s也就被修改了,内部是【1,2】这个列表被修改了。但只修改第一层的时候,s的第一层的元素的内存空间没有变,为了让s3【4】变成109,就又开辟了一个内存空间,里面存放了109,然后让s3【4】指向109所在的内存地址。
# 修改列表内部列表
s = [[1,2],1,2,3,4,5,6]
s3 = s.copy()
print(s3) # [[1, 2], 1, 2, 3, 4, 5, 6]
s3[0][1] = 3
print(s) # [[1, 3], 1, 2, 3, 4, 5, 6] 对s3的修改造成了对s的修改
print(s3) # [[1, 3], 1, 2, 3, 4, 5, 6]
# 只修改第一层中的简单元素
s = [[1,2],1,2,3,4,5,6]
s3 = s.copy()
s3[4] = 109
print(s3) # [[1, 2], 1, 2, 3, 109, 5, 6]
print(s) # [[1, 2], 1, 2, 3, 4, 5, 6]
第二种情况:b = a,这是将b直接指向了a所在的空间,由于这是列表,和一般的变量不一样,当这时候对b做出修改的时候,不会重新创建一个列表,把新列表的地址传给b,而是直接会对a 、b 共同的内存地址中的元素进行修改。下面的代码中可以看出s和s2的地址是一样的。也就是说,这时候b和a是一致的,换句话说,此时,b没有起到成为a备份的作用。
s = [[1,2],1,2,3,4,5,6]
s3 = s.copy()
s2 = s
s2[4] = 109
print(id(s2),'****',s2) # 139887398437384 **** [[1, 2], 1, 2, 3, 109, 5, 6]
print(id(s),'****',s) # 139887398437384 **** [[1, 2], 1, 2, 3, 109, 5, 6]
深浅拷贝代码
import copy
s = [[1,2],1,2,3,4,5,6]
s1 = copy.copy(s)
s2 = copy.deepcopy(s)
# s1[0][1] = 1000 # 浅拷贝只是拷贝一层
s2[0][1] = 1000 # 深拷贝不会影响原来的值,
print(s,s1,s2) # [[1, 2], 1, 2, 3, 4, 5, 6] [[1, 2], 1, 2, 3, 4, 5, 6] [[1, 1000], 1, 2, 3, 4, 5, 6]
print(id(s[0]),id(s1[0]),id(s2[0])) # 140256291818696 140256291818696 140256291818376
浅拷贝对副本的修改,会影响到原始数据
深拷贝对副本的修改,不会影响到原始数据
可以看到,s1第一个元素和第二个元素的位置是一样的,但是s2的第一个元素的地址就不一样
s1 = copy.copy(s)
s2 = copy.deepcopy(s)
# s1[0][1] = 1000 # 浅拷贝只是拷贝一层
s2[0][1] = 1000 # 深拷贝不会影响原来的值,
s2[4] = 1000
print(s,s1,s2) # [[1, 2], 1, 2, 3, 4, 5, 6] [[1, 2], 1, 2, 3, 4, 5, 6] [[1, 1000], 1, 2, 3, 1000, 5, 6]
print(id(s[4]),id(s1[4]),id(s2[4])) # 10919520 10919520 140625212407600
就算是对第一层的元素进行修改,也会像变量那样,重新创建一个内存空间,不会对原始数据产生影响。
浅拷贝的和深拷贝的在对第一层元素进行修改的时候,没有区别,都是重新创建一个新的空间,不会影响原始数据
但是深浅的区别在于,对于浅拷贝,对第二层元素进行修改的时候,会影响到原始数据。