从字面意思理解,拷贝即复制当前的对象。但是
只有在容器对象(列表,元组,字典)才有拷贝这一概念,原子对象(数字,字符串)没有拷贝这一说。
普通的复制都是浅拷贝。
浅拷贝可以理解为A容器拷贝产生的B容器虽然是新的,但B容器里的内容仍是旧的,其只是简简单单的复制了A容器里内容的引用,并没在B容器里创建真正的对象。而当我们修改B容器里的内容时,会产生两种结果:不可变对象会构建新的对象,其的id发生改变;而可变对象会根据引用去修改,结果其的改变会影响A容器里对应部分也发生改变。
为了使容器中可变对象的修改互不影响,得到真正意义上的拷贝,遂引出深拷贝这一概念,深拷贝也称为完全拷贝。
注:
id可以简单认为是地址(其实不是),“id(obj)”函数可以打印出obj对象的id。
可变对象是指其的内容可以发生改变,具体为列表,字典;不可变对象则反之,具体为数字,字符串和元组。
结合代码:
解除对应注释后,运行结果:
1)通过切片操作,工厂函数(list(),tuple(),dict())或copy模块的copy函数产生的都是浅拷贝。
2)浅拷贝得到的两个对象的id不同,但内容的id是相同的。若内容发生改变,不可变对象的id会变不同,彼此不影响;可变对象的id仍相同,彼此影响。
解除对应注释后,运行结果:
1)使用copy模块的deepcopy函数产生的是深拷贝。
2)深拷贝得到的两个对象的id不同,内容中可变对象id不同,内容中不可变对象id相同。如果内容发生改变,不可变对象id变不同,彼此不影响;可变对象id仍然不同,彼此不影响。
引入
普通的复制都是浅拷贝。
浅拷贝可以理解为A容器拷贝产生的B容器虽然是新的,但B容器里的内容仍是旧的,其只是简简单单的复制了A容器里内容的引用,并没在B容器里创建真正的对象。而当我们修改B容器里的内容时,会产生两种结果:不可变对象会构建新的对象,其的id发生改变;而可变对象会根据引用去修改,结果其的改变会影响A容器里对应部分也发生改变。
为了使容器中可变对象的修改互不影响,得到真正意义上的拷贝,遂引出深拷贝这一概念,深拷贝也称为完全拷贝。
注:
id可以简单认为是地址(其实不是),“id(obj)”函数可以打印出obj对象的id。
可变对象是指其的内容可以发生改变,具体为列表,字典;不可变对象则反之,具体为数字,字符串和元组。
结合代码:
#!/usr/bin/env python
# coding=utf-8
from copy import copy, deepcopy
def id_print(old, new):
print 'old对象:', old
print 'new对象:', new
print 'old对象与new对象的id:%d, %d' % (id(old), id(new))
print 'old[0]与new[0]的id:%d, %d' % (id(old[0]), id(new[0]))
print 'old[1]与new[1]的id:%d, %d' % (id(old[1]), id(new[1]))
old = ['old', ['old', 1]]
# new = old[:] # 切片,产生浅拷贝
# new = list(old) # 列表的工厂函数,产生浅拷贝
# new = copy(old) # copy模块的copy函数,产生浅拷贝
# new = deepcopy(old) # copy模块的deepcopy函数,产生深拷贝
print '*' * 20 + '修改前' + '*' * 20
id_print(old, new)
new[0] = 'new' # 修改不可变对象
new[1][0] = 'new' # 修改可变对象的内容
print '*' * 20 + '修改后' + '*' * 20
id_print(old, new)
浅拷贝与深拷贝的运行结果将在下面分别呈现。
浅拷贝
解除对应注释后,运行结果:
1)通过切片操作,工厂函数(list(),tuple(),dict())或copy模块的copy函数产生的都是浅拷贝。
2)浅拷贝得到的两个对象的id不同,但内容的id是相同的。若内容发生改变,不可变对象的id会变不同,彼此不影响;可变对象的id仍相同,彼此影响。
深拷贝
解除对应注释后,运行结果:
1)使用copy模块的deepcopy函数产生的是深拷贝。
2)深拷贝得到的两个对象的id不同,内容中可变对象id不同,内容中不可变对象id相同。如果内容发生改变,不可变对象id变不同,彼此不影响;可变对象id仍然不同,彼此不影响。
参考自Python核心编程第二版6.20节;文中如有不恰当的地方,还望包容和指出,感谢