深浅拷贝¶
深浅拷贝分两部分,一部分是数字和字符串另一部分是列表,元组,字典等其他数据类型
数字和字符串¶
对于数字
和字符串
而言,赋值,浅拷贝和深拷贝无意义,因为他们的值永远都会指向同一个内存地址
>>> import copy
>>> var1 = 123
>>> id(var1)
4297558784
>>> var2 = var1
>>> id(var2)
4297558784
>>> var3 = copy.copy(var1)
>>> id(var3)
4297558784
>>> var4 = copy.deepcopy(var1)
>>> id(var4)
4297558784
其他数据类型¶
对于字典,元组,列表而言,进行赋值,浅拷贝和深拷贝时,其内存地址的变化是不同的
创建一个字典var1
var1 = {"k1": "1", "k2": 2, "k3": ["abc", 456]}
赋值¶
赋值,只是创建一个变量,该变量指向原来内存地址
>>> var1 = {"k1": "1", "k2": 2, "k3": ["abc", 456]}
>>> var2 = var1
>>> id(var1)
4321886600
>>> id(var2)
4321886600
浅拷贝¶
# 导入拷贝模块
>>> import copy
>>> var1 = {"k1":"1","k2":2,"k3":["abc",456]}
# 使用浅拷贝的方式
>>> var2 = copy.copy(var1)
# 两个变量的内存地址是不一样的
>>> id(var1)
4321886536
>>> id(var2)
4324453960
# 但是他们的元素内存地址是一样的
>>> id(var1["k1"])
4322821824
>>> id(var2["k1"])
4322821824
如图所示:
浅copy的几种方式¶
import copy
a = ['a',['b',10]]
# 浅copy的三种方法
a1 = copy.copy(a)
a2 = a[:]
a3 = list(a)
a4 = copy.deepcopy(a)
a[1][0] = ["c"]
print(a)
print(a1)
print(a2)
print(a3)
print(a4)
运行结果
['a', [['c'], 10]]
['a', [['c'], 10]]
['a', [['c'], 10]]
['a', [['c'], 10]]
['a', ['b', 10]]
深拷贝¶
深拷贝,在内存中将所有的数据重新创建一份(排除最后一层,即:python内部对字符串和数字的优化)
# 导入拷贝模块
>>> import copy
>>> var1 = {"k1":"1","k2":2,"k3":["abc",456]}
# 使用深拷贝的方式把var1的内容拷贝给var2
>>> var2 = copy.deepcopy(var1)
# var1和var2的内存地址是不相同的
>>> id(var1)
4321886600
>>> id(var2)
4324386696
# var1和var2的元素"k3"内存地址是不相同的
>>> id(var1["k3"])
4325328136
>>> id(var2["k3"])
4325328072
# var1和var2的"k3"元素的内存地址是相同的
>>> id(var1["k3"][1])
4322765872
>>> id(var2["k3"][1])
4322765872
如图所示
总结¶
- Python中对象的赋值都是进行对象引用(内存地址)传递
- 使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的元素,依然使用原始的引用.
- 如果需要复制一个容器对象,以及它里面的所有元素(包含元素的子元素),可以使用copy.deepcopy()进行深拷贝
- 对于非容器类型(如数字、字符串、和其他’原子’类型的对象)没有被拷贝一说
- 如果元组变量只包含原子类型对象,则不能深拷贝,看下面的例子