在 Python 的分配语句理解上,我们可以看成类似指针的概念。但是我们要考虑两种情况,就是:
一、对数据的副本操作是否会影响原始数据?
二、对原始数据操作是否会影响副本数据?
那么我们从三方面来弄清楚复制对象机制:
第一,指向机制。
例如:
a =[[1,2,3],[4,5,6]]
a = b
在这种情况下,原始数据是一个二维列表,变量 a 指向了原始数据,对变量 a 的操作相当于对原始数据的操作。变量 b 相当于变量 a 的别名,所以对变量 b 的操作会改变 a 变量的值。
第二,浅层复制机制。
那么我们如果使用列表构造器来建立数据副本的话,例如:
c = list(a)
c is a # Fasle 说明副本建立成功
c[0] is a[0]# True 说明是浅层复制
那么变量 c 的值虽然与原始数据相同,但如果对 c[0]做操作的话,变量 a 的值依然不会改变,反之亦然。
这里要注意的是,当浅层复制原始数据未被改变之前,如果对 a[1][0]做操作的化,会改变 c 变量的值,反之亦然。这是因为 Python 的内置副本操作都是一种浅层复制。
这里的重点是,我们如何识别数据中原始数据与副本数据之间是否属于浅层复制?那么我们会使用 is 成员关系操作符来做数据对象之间的 id 判断。
第三,深层复制机制。
对于深层复制来说,Python 提供了一个 copy 标准库来实现数据的深层复制。例如:
import copy
d = copy.deepcopy(a)
d[0] is a[0]# False 说明实现了深层复制
这里要注意一点,在深层复制时,虽然例如:
d[0][0] is a[0][0]# True 原始数据内存地址一样
a[0][0]= 0
a[0][0] is d[0][0]# False 并不影响副本数据
重点是原始数据与副本数据完全是互不影响的。
那么这三种不同的机制,会根据数据对象的功能需求来配组使用。