一.什么是浅拷贝和深拷贝

       浅拷贝和深拷贝在Python中的对象参数传递中是一个非常重要的概念。
       浅拷贝是不拷贝子对象的内容,只拷贝子对象的引用。深拷贝是连子对象的内存也全部拷贝一份,对子对象的修改不修改源对象。
       这样说起来还是非常的抽象,我们来使用代码和图解来分析一下什么是浅拷贝和深拷贝,以及进行浅拷贝和深拷贝是内存中发生了什么。

Python中提供了copy模块,copy模块主要用于数据之间的拷贝。它提供了两个函数:
copy.copy(object):浅拷贝,返回object的浅拷贝
copy.deepcopy(object):深拷贝,返回object的深拷贝

我们使用这两个函数来测试浅拷贝与深拷贝

二.浅拷贝

我们以下面这段代码进行测试

import copy
a=[10,20,[5,6]]
b=copy.copy(a)

print("a:",a)
print("b:",b)
b.append(30)
b[2].append(7)

print("浅拷贝结果:")
print("a:",a)
print("b:",b)

这段代码简单易懂,我们来探究一下,代码运行过程中内存中到底发生了什么。
我们知道,Python中生成的对象都放在堆中,变量放在栈中,变量存放的不是对象的值,而是对象的地址(引用)。明白了这些,我们来分析第一段代码:

a=[10,20,[5,6]]
b=copy.copy(a)

新建了一个列表a,这个列表中有一个元素依然是列表,然后对a进行浅拷贝,并把返回结果存放到了b。可见浅拷贝的确是像我们之前说的那样,它不拷贝子对象的内容,只拷贝子对象的引用。也就是只拷贝了a指向的那个对象(父亲),并没有拷贝a指向对象的引用(儿子)

Python 浅拷贝 深拷贝 python中深浅拷贝_浅拷贝

b.append(30)
b[2].append(7)

这段代码是向b和b中的列表添加元素,内存分析如下

Python 浅拷贝 深拷贝 python中深浅拷贝_浅拷贝_02


可见,我们最后想要打印出来的a和b分别是[10,20,[5,6,7]]和[10,20,[5,6,7],30],a中没有30,但是b中有7,这就是浅拷贝的结果。

三.深拷贝

我们依然使用这段代码来说明深拷贝,只是copy.copy()改成了copy.deepcopy()

import copy
a=[10,20,[5,6]]
b=copy.deepcopy(a)

print("a:",a)
print("b:",b)
b.append(30)
b[2].append(7)

print("深拷贝结果:")
print("a:",a)
print("b:",b)

分析一下第一段代码中内存中的情况

a=[10,20,[5,6]]
b=copy.deepcopy(a)

新建了一个列表a,这个列表中有一个元素依然是列表,然后对a进行深拷贝,并把返回结果存放到了b。可见深拷贝是连子对象的内存也全部拷贝一份(父亲和儿子全都拷贝),但是对子对象的修改不修改源对象。

Python 浅拷贝 深拷贝 python中深浅拷贝_深拷贝_03

b.append(30)
b[2].append(7)

来看一下这时,向b中添加元素会发生什么:

Python 浅拷贝 深拷贝 python中深浅拷贝_Python 浅拷贝 深拷贝_04


可见,所有的修改都作用在了b上,而a没有发生任何的改变,对比浅拷贝,深拷贝真的是把父对象和子对象全部拷贝了一份。

以上就是一些浅拷贝与深拷贝的分析,如果有错误还请大家指正!