Python3中绑定关系对于初学者来说算是一个比较让人迷惑的了,本文争取用最简单的例子解释清楚。
浅拷贝
是指在复制过程中只复制一层变量,不会复制深层变量绑定的对象的拷贝过程。
使用方法如下:
L = [3.1, 3.2]
L1 = [1, 2, L]
L2 = L1.copy() # 等同于L2 = L1[:]
print(L1) # [1, 2, [3.1, 3.2]]
print(L2) # [1, 2, [3.1, 3.2]]
L2[2][0] = 3.14 # 重新赋值(见下图红色部分)
print(L1) # [1, 2, [3.14, 3.2]]
print(L2) # [1, 2, [3.14, 3.2]]
图例如下:
在python中,一般的赋值都等同于浅拷贝,绑定被拷贝变量所指向的对象,为了便于理解,我们列举下面几个例子:
# 示例1
a = 1
b = a
print(b) # 1
a = 2
print(b) # 1
如下图:
首先如图蓝色线,将变量a绑定对象1,拷贝之后是将变量b指向变量a所绑定的对象1,当将变量a赋值2时,b所绑定的对象是不变的。
#示例2
L = [1, 2, 3]
L1 = L
print(L) # [1, 2, 3]
print(L1) # [1, 2, 3]
L[1] = 5 # 对L[1]重新赋值
print(L) # [1, 5, 3]
print(L1) # [1, 5, 3]
如下图:
L首先绑定的是一个列表对象,然后列表中[0]、[1]、[2]元素再去分别绑定对象1,2,3,在将L赋值给L1时,是将L1指向L所绑定的列表对象,L[1] = 5操作如如红线部分,此时L和L1所绑定的列表对象没有变化,只是下一层列表的[1]元素所绑定的对象变成了5,所以在打印时L和L1的值都改变了。
看下面一个看似相同的例子:
L = [1, 2, 3]
L1 = L
print(L) # [1, 2, 3]
print(L1) # [1, 2, 3]
L = [4, 5, 6] # 对L重新赋值
print(L) # [4, 5, 6]
print(L1) # [1, 5, 3]
此时对L进行了重新绑定到别的列表对象,而L1所绑定的对象是不变的,所以最后打印出来的L和L1的结果是不一样的。
深拷贝
是指在复制过程中会拷贝每层所有绑定的对象(实际中不变对象除外如:数值、字符串等)。
示例如下:
import copy
L = [3.1, 3.2]
L1 = [1, 2, L]
L2 = copy.deepcopy(L1) # 如下如deepcopy示意
print(L1) # [1, 2, [3.1, 3.2]]
print(L2) # [1, 2, [3.1, 3.2]]
L1[2][0] = 3.14 # 如下图红色部分
print(L1) # [1, 2, [3.14, 3.2]]
print(L2) # [1, 2, [3.1, 3.2]]
注:图中所展示的数值对象,在值相同时实际只存储一次。