Amadeus's Studio.

深拷贝和浅拷贝

字数统计: 639阅读时长: 2 min
2019/02/28 Share

可变和不可变

可变类型(mutable):列表,字典;value值改变,id值不变;
不可变类型(unmutable):数字,字符串,元组;value值改变,id值也随之改变。

赋值,拷贝和深拷贝

赋值,只是创建一个变量,该变量指向原来内存地址,如下例:

1
n4 = n3 = n2 = n1 = "123/'Wu'"

"赋值"

浅拷贝,在内存中只额外创建第一层数据,如下图

1
2
3
import copy
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
n3 = copy.copy(n1)

浅拷贝

深拷贝,在内存中将所有的数据重新创建一份(递归拷贝,排除最后一层,即:python内部对字符串和数字的优化),如下图:

1
2
3
import copy
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
n4 = copy.deepcopy(n1)

深拷贝

字符串 数字 元祖拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 字符串
a = 'copytest'
b = copy.copy(a)
c = copy.deepcopy(a)

if __name__ == '__main__':
print(a, id(a))
print(b, id(b))
print(c, id(c))

#============输出结果===============#
copytest 49797384
copytest 49797384
copytest 49797384

整型数字,浮点型数字和元祖拷贝结果与字符串拷贝结果相同

列表拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
a = [1, 2, 5, [1, 3, 5]]
b = copy.copy(a)
c = copy.deepcopy(a)
b[-1].pop()

if __name__ == '__main__':
print(a, id(a))
print(b, id(b))
print(c, id(c))
#============输出结果===============#
[1, 2, 5, [1, 3]] 50059904
[1, 2, 5, [1, 3]] 50007496
[1, 2, 5, [1, 3, 5]] 50059584

单例模式下的类的拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def singleton(cls):
# 单例装饰器
instances = {}

@wraps(cls)
def get_instances(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]

return get_instances


@singleton
class Animal():
def __init__(self, name):
self.name = name

def aloud(self):
print(self.name + '123568')


a = Animal('cat')
b = copy.copy(a)
c = copy.deepcopy(a)
c.name = 'dog'
d = Animal('adas')

if __name__ == '__main__':
print(a, id(a))
a.aloud()
print(b, id(b))
b.aloud()
print(c, id(c))
c.aloud()
print(d, id(d))
d.aloud()

#============输出结果===============#
<__main__.Animal object at 0x02F67DD0> 49708496
cat123568
<__main__.Animal object at 0x02FACD90> 49991056
cat123568
<__main__.Animal object at 0x02FACAD0> 49990352
dog123568
<__main__.Animal object at 0x02F67DD0> 49708496
cat123568

不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。
一句话就是,不可变类型,不管是深拷贝还是浅拷贝,地址值和拷贝后的值都是一样的。

总结

1,深浅拷贝都是对源对象的复制,占用不同的内存空间。
2,不可变类型的对象,对于深浅拷贝毫无影响,最终的地址值和值都是相等的。
3,可变类型:
=浅拷贝: 值相等,地址相等
copy浅拷贝:值相等,地址不相等
deepcopy深拷贝:值相等,地址不相等

CATALOG
  1. 1. 可变和不可变
  2. 2. 赋值,拷贝和深拷贝
  3. 3. 字符串 数字 元祖拷贝
  4. 4. 列表拷贝
  5. 5. 单例模式下的类的拷贝
  6. 6. 总结