深浅拷贝

深浅拷贝分两部分,一部分是数字和字符串另一部分是列表,元组,字典等其他数据类型

数字和字符串

对于数字字符串而言,赋值,浅拷贝和深拷贝无意义,因为他们的值永远都会指向同一个内存地址

>>> 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
python-010-1

python-010-1

浅拷贝

# 导入拷贝模块
>>> 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

如图所示:

python-010-copy

python-010-copy

浅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-010-deepcopy

python-010-deepcopy

总结

  • Python中对象的赋值都是进行对象引用(内存地址)传递
  • 使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的元素,依然使用原始的引用.
  • 如果需要复制一个容器对象,以及它里面的所有元素(包含元素的子元素),可以使用copy.deepcopy()进行深拷贝
  • 对于非容器类型(如数字、字符串、和其他’原子’类型的对象)没有被拷贝一说
  • 如果元组变量只包含原子类型对象,则不能深拷贝,看下面的例子