python 的深浅拷贝是面试必问的问题,这里总结下:
- 不同的数据类型
- 不可变类型:
Number,String,Tuple都是不可变类型
- 可变类型
List,Dictionary,Set是可变数据类型,可以在当前地址空间内修改里面元素,而不需要开辟新的空间.
可变数据类型,至少有两层地址引用。
2,浅拷贝:
浅拷贝对于不可变类型,浅拷贝仅仅复制地址指向,不会开辟新的空间,对tuple也是这样操作!
a1 = 123123
a2 = 123123
a3=copy.copy(a1)
a4=copy.deepcopy(a1)
print(id(a1)) # 通过id()函数来打印变量在内存当中的地址
print(id(a2))
print(id(a3))#浅拷贝对于Number类型仅仅是对内存地址的引用拷贝
print(id(a4))
结果:
4429130768
4429130768
4429130768
4429130768
浅复制对于可变类型,会开辟新的地址空间,但是仅仅只是第一层元素开辟新的空间,里层的元素还是指向同一地址
l1=[1,2,'www',444,789,[4,3]]
l2=l1
l3=copy.copy(l1)
l4=copy.deepcopy(l1)
print(id(l1))
print(id(l2))
print(id(l3))#list开辟了新的地址空间
print(id(l4))
结果
4429160648
4429160648
4429159368
4429701000
对于可变元素,这里是list里面的元素,例如l1[2]='www',并没有复制一份,l1,l3都是指向同一地址的‘www’。对于里面的不可变元素也是如此。
print(id(l1[2]))
print(id(l3[2]))
print(id(l1[-1]))
print(id(l3[-1]))
结果:
4420585320
4420585320
4421217992
4421217992
3,深拷贝
深拷贝对于不可变元素 Number,String来说,与浅拷贝一样。
a1 = 123123
a2 = 123123
a3=copy.copy(a1)
a4=copy.deepcopy(a1)
print(id(a1)) # 通过id()函数来打印变量在内存当中的地址
print(id(a2))
print(id(a3))
print(id(a4))
b1="aasss"
b2="aasss"
b3=copy.deepcopy(b1)
print(id(b1)) # 通过id()函数来打印变量在内存当中的地址
print(id(b2))
print(id(b3))
结果:
4302949392
4302949392
4302949392
4302949392
4302855504
4302855504
4302855504
深拷贝对于tuple来说,若包含的都是不可变元素,则copy.deepcopy()相当于copy.copy(),都是引用指向。若包含有可变元素,则copy.deepcopy()是完全的深拷贝,依次拷贝每一个元素。
tt1=(1,2,'www',444,789)
tt2=copy.deepcopy(tt1)
print(id(tt1))
print(id(tt2))
tt3=(1,2,'www',444,789,[8,7,9])
tt4=copy.deepcopy(tt3)
print(id(tt3))
print(id(tt4))
结果:
4506318192
4506318192
4507481096
4507481192