Python中的直接赋值、浅拷贝和深拷贝都是涉及对象的一种操作,区别在于复制完成后两个对象是否独立,或者是否相互影响。也可以说是对变量赋值的一种方法,研究的都是可变类型的变量。
1.直接赋值
直接赋值就是使用原始地址,修改其中一个,另一个也跟着改变。
列表的直接赋值:
l0 = [2, 4, [6, 8]]
l1 = l0
print(l0, l1)
# 两个列表的地址一样
print(id(l0), id(l1))
# l0增加元素10,两个列表都会增加10这个元素
l0.append(10)
print(l0, l1)
# 列表l0中的列表增加元素9,l1列表中的对应列表也会增加元素9
l0[2].append(9)
print(l0, l1)
#[2, 4, [6, 8]] [2, 4, [6, 8]]
#1873787180288 1873787180288
#[2, 4, [6, 8], 10] [2, 4, [6, 8], 10]
#[2, 4, [6, 8, 9], 10] [2, 4, [6, 8, 9], 10]
字典的直接赋值:
d0 = {
"name": "画画",
"age": 13,
"address": ["河南", "江苏"]
}
d1 = d0
print(id(d0), id(d1))
d0["address"].append("山西")
print(d0, d1)
d0.pop("age")
print(d0, d1)
#字典的直接赋值与列表一样,此时两个字典的地址相同
#不管是哪一个字典中加入键值对、值增加内容,另一个字典的内容都会随之改变
#1816380472128 1816380472128
#{'name': '画画', 'age': 13, 'address': ['河南', '江苏', '山西']} {'name': '画画', 'age': 13, 'address': ['河南', '江苏', '山西']}
#{'name': '画画', 'address': ['河南', '江苏', '山西']} {'name': '画画', 'address': ['河南', '江苏', '山西']}
2.浅拷贝
浅拷贝: copy,不可变类型拷贝值,可变类型拷贝地址。
如列表:l0 = [2, 4, [6, 8]]中,2,4都是整型不可变类型,列表是可变类型。
列表的浅拷贝:
l0 = [2, 4, [6, 8]]
l1 = l0.copy()
# 外层列表的id不一致,说明拷贝的是值
print(id(l0), id(l1))
# 里边的嵌套的列表地址相同,说明拷贝的是地址
print(id(l0[2]), id(l1[2]))
print(l0, l1)
# 对外层列表增加内容,只增加l0的,l1不变
l0.append(10)
print(l0, l1)
# 对内层列表增加内容,都会增加内容
l0[2].append(5)
print(l0[2], l1[2])
#2079608558848 2079609621952
#2079609786240 2079609786240
#[2, 4, [6, 8]] [2, 4, [6, 8]]
#[2, 4, [6, 8], 10] [2, 4, [6, 8]]
#[6, 8, 5] [6, 8, 5]
字典的浅拷贝:
d0 = {
"name": "画画",
"age": 13,
"address": ["河南", "江苏"]
}
d1 = d0.copy()
# 字符串、数字是不可变类型
# 字典中的name、age直接拷贝值
# 列表是可变类型
# address拷贝地址
print(id(d0), id(d1))
print(id(d0["address"]), id(d1["address"]))
d0["address"].append("湖北")
print(d0, d1)
#67667796800 2367666737984
#2367668097600 2367668097600
#{'name': '画画', 'age': 13, 'address': ['河南', '江苏', '湖北']} {'name': '画画', 'age': 13, 'address': ['河南', '江苏', '湖北']}
3.深拷贝
在python中使用深拷贝时需要导入深拷贝。
深拷贝:deepcopy直接拷贝所有值。
from copy import deepcopy
列表的深拷贝:
# 地址不一样,所以两个列表的行为互不相关
l0 = [2, 4, [6, 8]]
l1 = deepcopy(l0)
print(id(l0), id(l1))
print(id(l0[2]), id(l1[2]))
l0.append(2)
print(l0, l1)
l0[2].append(3)
print(l0, l1)
#2425337304320 2425338367424
#2425338531712 2425338367360
#[2, 4, [6, 8], 2] [2, 4, [6, 8]]
#[2, 4, [6, 8, 3], 2] [2, 4, [6, 8]]
字典的深拷贝:
# 深拷贝,直接拷贝值,地址不一样
# 两个字典的行为互不干扰
d0 = {
"name": "画画",
"age": 13,
"address": ["河南", "江苏"]
}
d1 = deepcopy(d0)
print(id(d0), id(d1))
d0["address"].append("湖北")
print(d0, d1)
d0.update({"num": 1005})
print(d0, d1)
#2431570115392 2431570414976
#{'name': '画画', 'age': 13, 'address': ['河南', '江苏', '湖北']} {'name': '画画', 'age': 13, 'address': ['河南', '江苏']}
#{'name': '画画', 'age': 13, 'address': ['河南', '江苏', '湖北'], 'num': 1005} {'name': '画画', 'age': 13, 'address': ['河南', '江苏']}
小结
直接赋值后两个对象之间相互影响,不是独立的个体;浅拷贝对于外层还是独立的,但对于内层的可变类型对象还是可以相互影响的,即不可变类型拷贝值,可变类型拷贝地址;深拷贝后是两个独立的对象,两个对象之间的行为互不影响。
直接赋值、浅拷贝和深拷贝适用于不同的场景,可以根据需求选择合适的复制方式可以更好地管理对象之间的关系,帮助程序功能的实现。