学习
浅拷贝、深拷贝:
- 对于数字、字符串和元祖中的内存都指向同一个地址,所以深拷贝和浅拷贝对于他们都是无意义的
- 对于字典、列表和集合来说,进行浅拷贝和深拷贝时,内存的地址是不同的。
- 浅拷贝只会拷贝内存中的第一层数据,内存中地址的值都是完全相同的
- 而对于深拷贝将会把所有数据重新创建。
区别
浅拷贝:当改变拷贝对象的值,被拷贝对象的值不会被改变;
深拷贝:当改变拷贝对象的值,被拷贝对象的值也会被改变。
# 浅拷贝 + 深拷贝
import copy
def test10():
dict = {'key1': 'abc', 'key2': [123, 456]}
print('1原始id:',id(dict['key1']))
print('1原始id:',id(dict['key2'][0]))
new_copy_dict = copy.copy(dict)
print('2浅拷贝id:',id(new_copy_dict['key1']))
print('2浅拷贝id:', id(new_copy_dict['key2'][0]))
new_deep_dict = copy.deepcopy(dict)
print('2深拷贝id:',id(new_deep_dict['key1']))
print('2深拷贝id:', id(new_deep_dict['key2'][0]))
print('3原对象值:', dict['key2'][0])
print('3原始对象id:', id(dict['key2'][0]))
new_copy_dict['key2'][0] = "java"
new_deep_dict['key2'][0] = "python"
print('3修改对象值,浅拷贝:', new_copy_dict['key2'][0])
print('3修改对象值,浅拷贝id:', id(new_copy_dict['key2'][0]))
print('3修改对象值,深拷贝:',new_deep_dict['key2'][0])
print('3修改对象值,深拷贝id:', id(new_deep_dict['key2'][0]))
结果打印:
1原始id: 140625601436616
1原始id: 4410489840
2浅拷贝id: 140625601436616
2浅拷贝id: 4410489840
2深拷贝id: 140625601436616
2深拷贝id: 4410489840
3原对象值: 123
3原始对象id: 4410489840
3修改对象值,浅拷贝: java
3修改对象值,浅拷贝id: 140625601487624
3修改对象值,深拷贝: python
3修改对象值,深拷贝id: 140625609319400
应用
为什么Python默认的拷贝方式是浅拷贝?
- 时间角度:浅拷贝花费时间更少;
- 空间角度:浅拷贝花费内存更少;
- 效率角度:浅拷贝只拷贝顶层数据,一般情况下比深拷贝效率高。
扩展
在Python中可变与不可变对象
- 可变对象: 列表、字典、集合。所谓可变是指可变对象的值可变,身份是不变的。
- 不可变对象:数字、字符串、元组。不可变对象就是对象的身份和值都不可变。新创建的对象被关联到原来的变量名,旧对象被丢弃,垃圾回收器会在适当的时机回收这些对象。
可变对象与不可变对象的传值逻辑