python中深浅拷贝的讲解

拷贝,原则上就是把数据分离,使得源数据和副本数据的修改互不影响。在Python中,拷贝是有深、浅之分的,如果使用的时候不注意,就可能产生意外的结果。其实这个是由于共享内存导致的结果。

一、不可变数据类型

Python中不可变数据类型包括整型、浮点数、布尔值、字符串、元组。

1、赋值

对不可变数据类型来说,等号赋值并不会在内存中创建新的地址,只是多了一个引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 整型
a1 = 123
a2 = a1
print(id(a1), id(a2))

# 浮点数
b1 = 1.123
b2 = b1
print(id(b1), id(b2))

# 字符串
c1 = 'hello'
c2 = c1
print(id(c1), id(c2))

# 布尔值
d1 = True
d2 = d1
print(id(d1), id(d2))

# 元组
e1 = (1, 2, 3, 'hkey')
e2 = e1
print(id(e1), id(e2))

2、浅拷贝

对不可变数据类型使用浅拷贝,不会在内存中创建新的地址。

1
2
3
4
5
6
import copy

a1 = 'hello'
a2 = copy.copy(a1)

print(id(a1), id(a2))

3、深拷贝

对不可变数据类型使用深拷贝,不会在内存中创建新的地址。

1
2
3
4
5
6
import copy

a1 = 'hello'
a2 = copy.deepcopy(a1)

print(id(a1), id(a2))

二、可变数据类型

Python中可变数据类型包括列表、字典。

1、赋值

对可变数据类型来说,等号赋值并不会在内存中创建新的地址,只是多了一个引用。

1
2
3
4
n1 = {'k1': 'wu', 'k2': 123, 'k3': ['alex', 678]}
n2 = n1

print(id(n1), id(n2))

2、浅拷贝

对可变数据类型使用浅拷贝,只将第一层结构拷贝到了新的内存地址,更深层的则没有。

1
2
3
4
5
6
7
8
9
10
import copy

n1 = {'k1': 'wu', 'k2': 123, 'k3': ['alex', 678]}
n2 = copy.copy(n1) # 浅拷贝
print('第一层字典的内存地址:')
print(id(n1))
print(id(n2))
print('第二层嵌套的列表的内存地址:')
print(id(n1['k3']))
print(id(n2['k3']))

3、深拷贝

对可变数据类型使用深拷贝,将各层结构都拷贝到了新的内存地址。注意,对于里面的最小元素,如数字和字符串,它们的地址还是不变的。

1
2
3
4
5
6
7
8
9
10
import copy

n1 = {'k1': 'wu', 'k2': 123, 'k3': ['alex', 678]}
n2 = copy.deepcopy(n1) # 深拷贝
print('第一层字典的内存地址:')
print(id(n1))
print(id(n2))
print('第二层嵌套的列表的内存地址:')
print(id(n1['k3']))
print(id(n2['k3']))