python的深拷贝和浅拷贝

# 对象赋值
a = 'hello world'
b = a
print('a:',a,', b:',b)
# a: hello world , b: hello world
print(id(a)==id(b))
# True
a = 'Hello World'
print('a:',a,', b:',b)
# Hello World , b: hello world
print(id(a)==id(b))
# False


a = 1
b = a
print('a:',a,', b:',b)
# a: 1 , b: 1
print(id(a)==id(b))
# True
a = 2
print('a:',a,', b:',b)
# a: 2 , b: 1
print(id(a)==id(b))
# False


a = ['x','y',[1,2,3]]
b = a
print('a:',a,', b:',b)
# a: ['x', 'y', [1, 2, 3]] , b: ['x', 'y', [1, 2, 3]]
print(id(a)==id(b))
# True
a.append('hello')
print('a:',a,', b:',b)
# a: ['x', 'y', [1, 2, 3], 'hello'] , b: ['x', 'y', [1, 2, 3], 'hello']
print(id(a)==id(b))
# True
a[2].append(4)
print('a:',a,', b:',b)
# a: ['x', 'y', [1, 2, 3], 'hello'] , b: ['x', 'y', [1, 2, 3], 'hello']
print(id(a)==id(b))
# True

"""
所以在python中,对象的赋值都是进行对象引用(内存地址)传递,只要a的内存地址没有变化,a和b的内容都会始终一样。
"""

a = ['x','y',[1,2,3]]
b = a[:]
print('a:',a,', b:',b)
# a: ['x', 'y', [1, 2, 3]] , b: ['x', 'y', [1, 2, 3]]
print(id(a)==id(b))
# False
print([id(i) for i in a])
# [2059734973832, 2059735268016, 2059766662792]
print([id(i) for i in b])
# [2059734973832, 2059735268016, 2059766662792]

a.append('hello')
print('a:',a,', b:',b)
# a: ['x', 'y', [1, 2, 3], 'hello'] , b: ['x', 'y', [1, 2, 3]]
print(id(a)==id(b))
# False
a[2].append(4)
print('a:',a,', b:',b)
# a: ['x', 'y', [1, 2, 3, 4], 'hello'] , b: ['x', 'y', [1, 2, 3, 4]]
print(id(a)==id(b))
# False

print('浅拷贝')
# 浅拷贝
import copy
a = ['x','y',[1,2,3,[4,5,6]]]
d = copy.copy(a)
print('a:',a,', b:',b)
# a: ['x', 'y', [1, 2, 3, [4, 5, 6]]] , b: ['x', 'y', [1, 2, 3, 4]]
print(id(a)==id(b))
# False
print([id(i) for i in a])
# [2640575102344, 2640603314864, 2640606922568]
print([id(i) for i in b])
# [2640575102344, 2640603314864, 2640606922824]
a[2].append(4)
print('a:',a,', b:',b)
# a: ['x', 'y', [1, 2, 3, [4, 5, 6], 4]] , b: ['x', 'y', [1, 2, 3, 4]]
tmp_list_a = a[2]
print(id(tmp_list_a))
# 2640606922568
print([id(i) for i in tmp_list_a])
# [1434892752, 1434892784, 1434892816, 2640606922632, 1434892848]
tmp_list_b = b[2]
print(id(tmp_list_b))
# 2640606922824
print([id(i) for i in tmp_list_b])
# [1434892752, 1434892784, 1434892816, 1434892848]

"""
所以在python(python3.6)中浅拷贝会将不可变元素的地址直接拷贝,而可变对象如list会用新的地址指向原list内存区域,相当于两个不同的指针指向同样的内存区。
"""

# 深拷贝

import copy
a = ['x','y',[1,2,3,[4,5,6]]]
b = copy.deepcopy(a)
print('a:',a,', b:',b)
# a: ['x', 'y', [1, 2, 3, [4, 5, 6]]] , b: ['x', 'y', [1, 2, 3, [4, 5, 6]]]
print(id(a)==id(b))
# False
print([id(i) for i in a])
# [2460486303112, 2460486597296, 2460490204808]
print([id(i) for i in b])
# [2460486303112, 2460486597296, 2460490204616]
tmp_list_a = a[2]
print(id(tmp_list_a))
# 2460490204808
print([id(i) for i in tmp_list_a])
# [1434892752, 1434892784, 1434892816, 2460490204872]
tmp_list_b = b[2]
print(id(tmp_list_b))
# 2460490204616
print([id(i) for i in tmp_list_b])
# [1434892752, 1434892784, 1434892816, 2460490204552]

"""
深拷贝,就是会递归的进行拷贝,直到查找到原子类型。
"""

# 补充:
"""
对于拷贝有一些特殊情况:
    对于非容器类型(如数字、字符串、和其他'原子'类型的对象)没有拷贝这一说
也就是说,对于这些类型,如果元祖变量只包含原子类型对象,则不能深拷贝。
 如下例子:
"""
a = (1,'x')
b = copy.copy(a)
print(id(a)==id(b))   #没有拷贝
# True
b = copy.deepcopy(a)
print(id(a)==id(b))   #没有拷贝
# True

a = (1,'x',[2])
b = copy.copy(a)
print(id(a)==id(b))   #没有拷贝
# True
b = copy.deepcopy(a)
print(id(a)==id(b))   #拷贝
# False

# 总结
"""
* Python中对象的赋值都是进行对象引用(内存地址)传递
* 使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的元素,依然使用原始的引用.
* 如果需要复制一个容器对象,以及它里面的所有元素(包含元素的子元素),可以使用copy.deepcopy()进行深拷贝
* 对于非容器类型(如数字、字符串、和其他'原子'类型的对象)没有被拷贝一说
* 如果元祖变量只包含原子类型对象,则不能深拷贝
"""
原文地址:https://www.cnblogs.com/sandy-t/p/8203647.html