## 一、问题引出浅拷贝

a = [1, 2, 3]

print('a = %s' % a)  # a = [1, 2, 3]

b = a

print('b = %s' % b) # b = [1, 2, 3]

a.append(4)  # 对a进行修改
print('a = %s' % a)  # a = [1, 2, 3, 4]
print('b = %s' % b)  # b = [1, 2, 3, 4]

b.append(5) # 对b进行修改
print('a = %s' % a)  # a = [1, 2, 3, 4, 5]
print('b = %s' % b)  # b = [1, 2, 3, 4, 5]

# 注意，不同机器上，这个值不同，但只要a，b两个变量的地址值是一样的就能说明问题了

print(id(a)) # 4439402312

print(id(b)) # 4439402312

## 二、如何进行深拷贝

python中实现深拷贝的方式很简单，只需要引入copy模块，调用里面的deepcopy()的方法即可，示例代码如下：

import copy
a = [1, 2, 3]
b = copy.deepcopy(a)

print('a = %s' % a) # a = [1, 2, 3]
print('b = %s' % b) # b = [1, 2, 3]

b.append(4)
print('a = %s' % a) # a = [1, 2, 3]
print('b = %s' % b) # b = [1, 2, 3, 4]

print(id(a)) # 4321416008
print(id(b)) # 4321416200

## 三、copy模块方法简介

1. 返回值是对这个对象的深拷贝

2. 如果拷贝发生错误，会报copy.err异常

3. 存在两个问题，第一是如果出递归对象，会递归的进行拷贝，第二正因为会递归拷贝，会导致出现拷贝过多的情况

4. 关于两种拷贝方式的区别都是相对是引用对象

import copy
a = [1, 2, 3]
b = [3, 4, 5]

c = [a, b] # 列表嵌套

d = copy.deepcopy(c)
print('c = %s' % c) # c = [[1, 2, 3], [3, 4, 5]]
print('d = %s' % d) # d = [[1, 2, 3], [3, 4, 5]]

c.append(4)
print('c = %s' % c) # c = [[1, 2, 3], [3, 4, 5], 4]
print('d = %s' % d) # d = [[1, 2, 3], [3, 4, 5]]

c[0].append(4) # 相当于a.append(4)
print('c = %s' % c) # c = [[1, 2, 3, 4], [3, 4, 5], 4]
print('d = %s' % d) # d = [[1, 2, 3], [3, 4, 5]]

# a.append(4)
# print('c = %s' % c) # a = [1, 2, 3]
# print('d = %s' % d) # b = [1, 2, 3]

print(id(c)) # 4314188040
print(id(d)) # 4314187976

print(id(c[0])) # 4314186568
print(id(d[0])) # 4314187912

print(id(a)) # 4314186568
print(id(b)) # 4314186760

官方文档解释的很简单，它返回的就是对象的浅拷贝。但其实它会对最外层进行深拷贝，而如果有多层，第二层以后进行的就是浅拷贝了。代码示例如下：

import copy
a = [1, 2, 3]
b = [3, 4, 5]

c = [a, b] # 列表嵌套

d = copy.copy(c)

print('c = %s' % c) # c = [[1, 2, 3], [3, 4, 5]]
print('d = %s' % d) # d = [[1, 2, 3], [3, 4, 5]]

c.append(4)
print('c = %s' % c) # c = [[1, 2, 3], [3, 4, 5], 4]
print('d = %s' % d) # d = [[1, 2, 3], [3, 4, 5]]  没有发生变化，说明外层是深拷贝

c[0].append(4) # 相当于a.append(4)
print('c = %s' % c) # c = [[1, 2, 3, 4], [3, 4, 5], 4]
print('d = %s' % d) # d = [[1, 2, 3, 4], [3, 4, 5]] 发生了变化，说明内层是浅拷贝

# a.append(4)
# print('c = %s' % c) # c = [[1, 2, 3, 4], [3, 4, 5], 4]
# print('d = %s' % d) # d = [[1, 2, 3, 4], [3, 4, 5]] 发生了变化，说明内层是浅拷贝

print(id(c)) # 4322576648
print(id(d)) # 4322576584 d和c地址不同，进一步说明外层是深拷贝

print(id(c[0])) # 4322575176
print(id(d[0])) # 4322575176 c[0]和d[0]地址相同，进一步说明内层是浅拷贝

print(id(a)) # 4322575176
print(id(b)) # 4322575368

【注意】对于copy()方法，有特殊情况，比如元组类型，代码示例如下：

import copy
a = [1, 2, 3]
b = [3, 4, 5]

c = (a, b) # 列表改成元组

d = copy.copy(c)

print(id(c)) # 4303015752
print(id(d)) # 4303015752 d和c地址相同

print(id(c[0])) # 4322575176
print(id(d[0])) # 4322575176 c[0]和d[0]地址相同，进一步说明内层是浅拷贝

## 四、关于“修改”的一点说明

import copy
a = [1, 2, 3]
b = a
a = [3, 4, 5]
print(a) # [3, 4, 5]
print(b) # [1, 2, 3]

posted on 2018-01-05 11:41 DemonFS 阅读(...) 评论(...) 编辑 收藏