九浅一深(深浅拷贝)

*拷贝python对象(浅拷贝、深拷贝)

浅拷贝——
对一个“对象”进行浅拷贝其实就是新创建了一个类型跟原对象一样,内容是原来对象元素的引用,
换句话说:这个拷贝的对象本身是新的,但是内容不是。

什么情况下是浅拷贝:
1、完全切片 [:]
2、工厂函数 比如:list(),dict()
3、使用copy模块的copy函数

演示浅拷贝特性

#!/usr/bin/env python3
#-*- coding:utf-8 -*-

count = ['name',['saveings',100]]

wife = count[:]

husband = list(count)

def view_list(*a):
print(a)

def view_id(*a):
for i in a:
print(id(i))

view_list(wife,husband)
view_id(count,wife,husband)

wife[0] = 'Nichole'
husband[0] = 'Alben'

wife[1][1] = 50

view_list(wife,husband)

解析:
定义1个count列表,其中两个元素,‘name’、‘[’saveings’,100]

列表wife 通过完全切片拷贝而来

列表husband 通过工厂拷贝而来

第一次调用函数:view_list,结果
(['name', ['saveings', 100]], ['name', ['saveings', 100]])
第一次调用函数:view_id,结果
34359816
34360056
34360976
从id的值上看,这三个列表都是不同的对象。

把"wife","husband"列表中的第一个值重定义:
wife[0] = 'Nichole'
husband[0] = 'Alben'
把wife列表第二个元素(列表)中的第二个元素改为100(意味着老婆取款50)

第二次运行函数:view_list与view_id的结果:
(['Nichole', ['saveings', 50]], ['Alben', ['saveings', 50]])
34228744
34228984
34229904

我们会发现,"wife"和"husband"两个列表第二个元素中的第二个元素都改变了!

why?
因为是浅拷贝!
但是为什么在修改"husband"列表[0]值的时候,没有同时修改"wife"呢?
因为"wife","husband"两个列表的第一个元素是字符串(不可变对象)
但是第二个元素时列表,是可变对象。
所以在拷贝的时候,字符串被显式的拷贝了,并且创建了新的字符串对象,而列表只是把它的引用复制了一下,
所以改变第二个对象的时候是两个引用会同时变化。

验证:
改变前
print([id(x) for x in wife])
print([id(x) for x in husband])
结果:
[4006400, 37112288]
[4006400, 37112288]
改变后:
[34288320, 34294240]
[34288384, 34294240]

这样就很明显了,两个列表第一个元素“字符串”改变后,id值是不同的,但是第二个元素“列表”的id值是相同的。

深拷贝:
通过copy()函数的deepcopy()功能。
修改上段代码:

#!/usr/bin/env python3
#-*- coding:utf-8 -*-

import copy

count = ['name',['saveings',100]]

wife = count

husband = copy.deepcopy(count)

def view_id(*a):
for i in a:
print(id(i))


def view_list(*a):
print(a)

 

wife[0] = 'Nichole'
husband[0] = 'Alben'

wife[1][1] = 50

view_list(wife,husband)

print([id(x) for x in wife])
print([id(x) for x in husband])

结果:
(['Nichole', ['saveings', 50]], ['Alben', ['saveings', 100]])
[34484928, 38064296]
[34484992, 38065256]
深拷贝是创建两个对象,所有id()结果两个元素对象的值都不同!

关于深拷贝的注意点:
第一,非容器类型(数字、字符串、其他‘原子’类型)没有被拷贝一说,例如元组,对他深拷贝是无效的。

原文地址:https://www.cnblogs.com/alben-cisco/p/6974399.html