深浅copy:完全复制和部分复制
== 是比较的两边的数值是否相等,而 is 是比较的两边的内存地址是否相等。
一、赋值运算
>>> list1 = [1, 2, 3, ['jacky', 'ku_gua']]
>>> list2 = list1
>>> list1[0] = 111
>>> print(list1) #[111, 2, 3, ['jacky', 'ku_gua']]
>>> print(list2) #[111, 2, 3, ['jacky', 'ku_gua']]
>>> list1[3][0] = 'jiexin'
>>> print(list1) #[111, 2, 3, ['jiexin', 'ku_gua']]
>>> print(list2) #[111, 2, 3, ['jiexin', 'ku_gua']]
>>> id(list1) #2810681910408
>>> id(list2) #2810681910408
对于赋值运算来说(list2 = list1 ),相当于给list1 另起一个名字叫做list2, list1与list2指向的是同一个内存地址,所以他们是完全一样的。
二、浅拷贝copy
#同一代码块和不同代码块下结果相同
>>> list1 = [1, 'jieixn', True, (1, 2, 3), [33, 44]]
>>> list2 = list1.copy()
>>> print(id(list1), id(list2)) # 2810681911624 2810681912328 两个列表的地址不一样
>>> print(id(list1[-1]), id(list2[-1])) # 2810681911560 2810681911560 [33, 44]的地址一样
>>> print(id(list1[-2]), id(list2[-2])) # 2810684591632 2810684591632 (1, 2, 3)的地址一样
对于浅copy来说,只是在内存中重新创建了开辟了一个空间存放一个新列表,但是新列表中的元素与原列表中的元素是公用的。
三、深拷贝deepcopy
#同一代码块和不同代码块下结果相同
>>> import copy
>>> list1 = [1, 'jieixn', True, (1, 2, 3), [33, 44]]
>>> list2 = list1.copy()
>>> print(id(list1), id(list2)) #1863448230472 1863448230280
>>> print(id(list1[0]), id(list2[0])) #140709557887824 140709557887824 两个列表地址不一样
>>> print(id(list1[-1]), id(list2[-1])) #1863448230088 1863448230088 [33, 44]的地址一样
>>> print(id(list1[-2]), id(list2[-2])) #1863450663096 1863450663096 (1, 2, 3)的地址不一样
对于深copy来说,列表是在内存中重新创建的,列表中可变的数据类型是重新创建的,列表中的不可变的数据类型是公用的。
四、一些例子
# 赋值运算
list1 = [1, 2, 3]
list2 = list1
list1.append('a')
print(list1, list2) # [1, 2, 3, 'a'] [1, 2, 3, 'a'
# copy
list1 = [1, 2, 3]
list2 = l1.copy()
print(list1, list2) # [1, 2, 3] [1, 2, 3]
print(id(l1), id(l2)) # 2212007672072 2212007672392
l2.append('a')
print(list1, list2) # [1, 2, 3] [1, 2, 3, 'a']
# copy
l1 = [1,2,[4,5,6],3]
l2 = l1.copy()
print(l1,id(l1)) # [1, 2, [4, 5, 6], 3] 2061635578184
print(l2,id(l2)) # [1, 2, [4, 5, 6], 3] 2061635578056
l1.append('a')
print(l1,l2) # [1, 2, [4, 5, 6], 3, 'a'] [1, 2, [4, 5, 6], 3]
l1[2].append('a')
print(l1,l2) #[1, 2, [4, 5, 6, 'a'], 3, 'a'] [1, 2, [4, 5, 6, 'a'], 3]
#浅copy()形成的列表,列表里面的元素重用,地址一样 此处:[4, 5, 6]
print(id(l1[2])) # 2061635578696
print(id(l2[2])) # 2061635578696
#deepcopy
import copy
l1 = [1,2,[4,5,6],3]
l2 = copy.deepcopy(l1)
print(l1,id(l1)) # [1, 2, [4, 5, 6], 3] 2767148513864
print(l2,id(l2)) # [1, 2, [4, 5, 6], 3] 2767148514248
#deepcopy()产生的列表内的可变数据类型与原列表内的不重用
l1[2].append('a')
print(l1,l2) # [1, 2, [4, 5, 6, 'a'], 3] [1, 2, [4, 5, 6], 3] #l2[2]没有添加元素‘a’
#列表切片copy :相当于浅copy
l1 = [1,[1],2,3,4]
l2 = l1[:]
l1[1].append('a')
print(l1) # [1, [1, 'a'], 2, 3, 4]
print(l2) # [1, [1, 'a'], 2, 3, 4]
print(l1,id(l1)) # [1, [1, 'a'], 2, 3, 4] 2426268580040
print(l2,id(l2)) # [1, [1, 'a'], 2, 3, 4] 2426268579912
print(l1[1] is l2[1]) # True
五、总结
1,深浅拷贝都是对源对象的复制,占用不同的内存空间。
2,不可变类型的对象,对于深浅拷贝毫无影响,最终的地址值和值都是相等的。
3,可变类型:
=浅拷贝: 值相等,地址相等
copy浅拷贝:值相等,地址不相等 (切片赋值是浅拷贝,只拷贝外侧列表,子列表与原列表公用一份,如果原列表的最外层增删改查,浅拷贝后的列表不变。但是如果原列表的子列表增删改查,浅拷贝后的子列表变化)
deepcopy深拷贝:值相等,地址不相等