Python浅拷贝和深拷贝
目录
1.浅拷贝和深拷贝的特点
使用内置函数:copy(浅拷贝)、deepcopy(深拷贝)。
浅拷贝:不拷贝子对象的内容,只是拷贝子对象的引用。
深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源对象。
形
象
比
喻
\color{orange}{形象比喻}
形象比喻
浅拷贝:拷贝当前个体
深拷贝:拷贝当前个体及其整个家族
2.浅拷贝和深拷贝原理
由两幅图对比可以发现,浅拷贝只是拷贝了当前个体,深拷贝则是拷贝当前个体及其整个家族。
3.浅拷贝和深拷贝操作
3.1 浅拷贝和深拷贝操作的底层逻辑
变量产生的底层逻辑这里就不详细说明,可参考变量产生的底层逻辑。
3.1.1 浅拷贝操作的底层逻辑
①b = copy.copy(a)
把
a
\color{red}{a}
a 浅拷贝给
b
\color{blue}{b}
b
浅拷贝只copy了当前对象个体,不拷贝其后代元素。当前对象个体内各元素依次指向原体的下一层后代。
②b.append(30)
在复制体
b
\color{blue}{b}
b 中添加元素
i
n
t
(
30
)
\color{green} {int(30)}
int(30)
③b[2].append(7)
在第一层后代添加元素
i
n
t
(
7
)
\color{green} {int(7)}
int(7)
b[2]
定位到了
a
\color{red} {a}
a 和
b
\color{blue} {b}
b 共同指向的第二个子元素,即列表元素。b[2].append(7)
在列表中添加新元素
i
n
t
(
7
)
\color{green} {int(7)}
int(7) 。
因此执行完b = copy.copy(a)
、b.append(30)
、b[2].append(7)
后,
a
\color{red} {a}
a 的列表子对象中多了元素
i
n
t
(
7
)
\color{green} {int(7)}
int(7),
b
\color{blue} {b}
b 中多了
i
n
t
(
30
)
\color{green} {int(30)}
int(30)子对象并且b的列表子对象中多了元素
i
n
t
(
7
)
\color{green} {int(7)}
int(7)。
简单测试:
浅拷贝:自身的复制体(后称"自复体")操作不会影响被复制体自身(后称"自原体"),但通过自复体对后代操作会影响自原体的后代(因为自原体和自复体都指向了共同点的后代)。
3.1.2 深拷贝操作的底层逻辑
①b = copy.deepcopy(a)
把
a
\color{red}{a}
a 深拷贝给
b
\color{blue}{b}
b
深拷贝不仅copy了当前对象个体,也拷贝其后代元素。
②b.append(30)
在复制体
b
\color{blue}{b}
b 中添加元素
i
n
t
(
30
)
\color{green} {int(30)}
int(30)
③b[2].append(7)
在第一层后代添加元素
i
n
t
(
7
)
\color{green} {int(7)}
int(7)
b[2]
定位到了自身的第二个子元素,即自身的列表元素。b[2].append(7)
在列表中添加新元素
i
n
t
(
7
)
\color{green} {int(7)}
int(7) 。
因此执行完b = copy.copy(a)
、b.append(30)
、b[2].append(7)
后,
a
\color{red} {a}
a 没有任何变化,
b
\color{blue} {b}
b 中多了
i
n
t
(
30
)
\color{green} {int(30)}
int(30)子对象并且b的列表子对象中多了元素
i
n
t
(
7
)
\color{green} {int(7)}
int(7)。
简单测试:
深拷贝:复制了一整套自身和自身的后代。自身的复制体(后称"自复体")操作不会影响被复制体自身(后称"自原体"),通过自复体对后代操作也不会影响自原体的后代(因为自原体和自复体分别指向自己的后代,互不相干)。