写在前面的
- 我们知道python3里面的整数存储是先在内存中找到空间存好数值,然后再把整数的引用传递给变量,同一个整数只分配一次内存,比如:
a = 18
b = 18
id(a)
id(b)
- 变量给变量赋值,实际上就是把变量指向的值的引用赋值给新的变量,比如:
c = [1, 2, 3]
d = [1, 2, 3]
e = c
id(c)
id(d)
id(e)
- 这就是python里面关于变量和引用的关系,如果我们通过列表方法修改e的值,c的值也会跟着改变:
c.append(4)
然后我们从copy模块来说起
copy.copy()
- 这个方法的作用就是完成浅拷贝
- 什么是浅拷贝?
- 通俗的来讲:假如一个变量是列表或者元组字典这种具有多层次结构的类型
- 浅拷贝就只是改变了最外层的引用值,而里面不管是什么数值,他们的引用都是相同的,比如:
import copy
a1 = [1, 2, 3, 4]
a2 = [7, 8]
b1 = [a1, a2]
b2 = copy.copy(b1)
id(b1)
id(b2)
id(b1[0])
id(b2[0])
a2.append(9)
- 还有一种特殊情况,如果最外层是元组的话,那么连最外层的引用都不会变:
c1 = (a1, a2)
c2 = copy.copy(c1)
id(c1)
id(c2)
copy.deepcopy()
- 这个就是深拷贝
- 那么什么具体什么是深拷贝呢?
- 很简单,同上面来讲就一点区别,就是不光是最外层,连里层所有的数值的引用也全都发生改变了
b3 = copy.deepcopy(b1)
id(b3)
id(b3[0])
c3 = copy.deepcopy(c1)
id(c3)
- 那么有特殊情况吗?也有,就是内外全部都是不可变类型,比如内外都是元组类型的,那么deepcopy也根本就不拷贝,也就是说由内而外的引用全部不变
d1 = (3, 4, 5)
d2 = (6, 7, 8)
e1 = (d1, d2)
e2 = copy.deepcopy(e1)
id(e1)
id(e2)
id(e1[0])
id(e2[0])
深拷贝和浅拷贝的区别
- 深拷贝相当于完全拿一份过来,拷贝源的修改对于它没有任何影响
- 浅拷贝来说,对于拷贝源通过列表或者字典方法进行修改时,是会受到影响的
其他形式的拷贝
b4 = b1[:]
id(b4)
id(b4[0])
- 字典的copy方法相当于浅拷贝:
- 是字典的copy方法,不是copy模块的copy方法
item1 = {"a": 12, "b": 13, "c":14}
item2 = item1.copy()
id(item1)
id(item2)
id(item1["a"])
id(item2["a"])