标签:深浅copy bsp 地址 不可变 ack 通过 append app code
学习深浅copy之前,我们先来看一个例子
1 l1 = [1, 2, 3] 2 l2 = l1 3 l2.append(4) 4 print(l1, l2)
猜猜结果是怎样的?l1是打印[1,2,3]还是[1,2,3,4],来看结果
[1, 2, 3, 4] [1, 2, 3, 4]
看到没,l2添加了一个元素4后l1也跟着改变,这说明l1,l2指向的是同一个内存地址,我们可以用is验证一下
print(l1 is l2)
执行结果
True
说明l1和l2的指向同一个内存地址,l1,l2的内存地址相同,那么它们的元素的内存地址是否相同呢,来看
print(id(l1[0]), id(l2[0]))
执行结果
1445227552 1445227552
元素的内存地址也相同,列表里的元素不仅仅是数字,也可以是列表或者字典等可变数据类型,那么对于这些可变数据类型,它们的内存地址是否相同呢,来看代码
1 l1 = [1, 2, [3, 4, 5]] 2 l2 = l1 3 print(id(l1), id(l2)) 4 print(id(l1[1]), id(l2[1])) 5 print(id(l1[-1]), id(l2[-1]))
执行结果
1950802883592 1950802883592 1445227584 1445227584 1950802883656 1950802883656
可见对于可变数据类型,内存地址也是相同的。因此我们可以得出结论,对于赋值运算,是将原对象的内存地址赋值给新对象,等号两边的对象的内存地址和元素的内存地址都是完全相同的。
浅copy是利用列表或字典的copy方法来复制,其内部机制是怎样的呢,来看一段代码
1 l1 = [1, "abc", [1, 2]] 2 l2 = l1.copy() 3 print(id(l1), id(l2)) # 内存地址不同 4 print(id(l1[0]), id(l2[0])) 5 print(id(l1[-1]), id(l2[-1])) # 内存地址相同 6 l1.append(3) 7 print("l1 ", l1) 8 print("l2 ", l2) # l2没有加上3 9 l1[-2].append(3) 10 print("l1 ", l1) 11 print("l1 ", l2)
执行结果
1156212831240 1156212831432
1445227552 1445227552
1156212831304 1156212831304
l1 [1, ‘abc‘, [1, 2], 3]
l2 [1, ‘abc‘, [1, 2]]
l1 [1, ‘abc‘, [1, 2, 3], 3]
l1 [1, ‘abc‘, [1, 2, 3]]
再来看看字典
1 dic1 = {1: "a", 2: "b", 3: [1, 2, 3]} 2 dic2 = dic1.copy() 3 print(id(dic1), id(dic2)) 4 print(id(dic1[1]), id(dic2[1])) 5 print(id(dic1[3]), id(dic2[3])) 6 dic1[4] = "m" 7 print(dic1) 8 print(dic2) 9 dic1[3].append(4) 10 print(dic1) 11 print(dic2)
执行结果
2260199788616 2260199788688 2260199617232 2260199617232 2260229796936 2260229796936 {1: ‘a‘, 2: ‘b‘, 3: [1, 2, 3], 4: ‘m‘} {1: ‘a‘, 2: ‘b‘, 3: [1, 2, 3]} {1: ‘a‘, 2: ‘b‘, 3: [1, 2, 3, 4], 4: ‘m‘} {1: ‘a‘, 2: ‘b‘, 3: [1, 2, 3, 4]}
可以看出,浅copy的机制是:
也就是说创建了一个新的容器,但是里面的内容跟原容器是一样的,原容器的原内容(不包括新添加的)发生改变,新容器的对应内容也会发生改变。
浅copy不仅可以通过copy方法,还可以通过列表的切片
1 l1 = [1, "abc", [1, 2]] 2 l2 = l1[:] 3 print(id(l1), id(l2)) # id不一样
执行结果
2183077803016 2183077803208
因此列表的切片(全切)是浅copy
深copy可以利用copy模块里的deepcopy方法
1 import copy 2 l1 = [1, "abc", [1, 2]] 3 l2 = copy.deepcopy(l1) 4 print(id(l1), id(l2)) 5 print(id(l1[0]), id(l2[0])) # 内存地址相同(不可变数据类型) 6 print(id(l1[1]), id(l2[1])) # 内存地址相同 7 print(id(l1[-1]), id(l2[-1])) # 内存地址不同(可变数据类型)
执行结果
2267524916744 2267524918024 1445227552 1445227552 2267522383976 2267522383976 2267524916552 2267524917960
由此我们可以总结深copy的原理:
标签:深浅copy bsp 地址 不可变 ack 通过 append app code
原文地址:https://www.cnblogs.com/zzliu/p/10192785.html