您的位置:首页 > 编程语言 > Python开发

详解python中的浅拷贝和深拷贝

2017-11-07 18:03 155 查看
一、定义

首先比较直观的说一下,python里面的浅拷贝和深拷贝

浅拷贝:就是对引用的拷贝,值拷贝父对象

深拷贝:就是对对象的资源的拷贝

首先下面通过我们常常说的赋值来看一下:

root@ubuntu16:~# python3

Python 3.5.2 (default, Sep 14 2017, 22:51:06)

[GCC 5.4.0 20160609] on linux

Type “help”, “copyright”, “credits” or “license” for more information.

a = [1,2,’a’,’b’]

b = a

b

[1, 2, ‘a’, ‘b’]

a

[1, 2, ‘a’, ‘b’]

a.append(‘c’)

a

[1, 2, ‘a’, ‘b’, ‘c’]

b

[1, 2, ‘a’, ‘b’, ‘c’]

id(a)

140489872264776

id(b)

140489872264776

在python中,对象赋值实际上是对象的引用。当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用。上面首先定义一个列表a,然后将a赋值给b,可以看到a和b的值是一样的,我们在修改a的值的时候【比如添加一个字符c】,b的值也是一样的跟着变化的,这是因为a和b分别是两个标签,但他们引用的是同一个地址空间,我们能看到id(a),id(b)是同样的值,即是同一个地址空间。

二、举例解释:

root@ubuntu16:~# python3

Python 3.5.2 (default, Sep 14 2017, 22:51:06)

[GCC 5.4.0 20160609] on linux

Type “help”, “copyright”, “credits” or “license” for more information.

import copy

首先导入copy模块,因为后面要用到copy函数

a = [1,2,3,4,[‘a’,’b’,’c’],{‘name’:’liang’}]

b = a

b

[1, 2, 3, 4, [‘a’, ‘b’, ‘c’], {‘name’: ‘liang’}]

在这里还是把a的值赋值给b

c = copy.copy(a)

c

[1, 2, 3, 4, [‘a’, ‘b’, ‘c’], {‘name’: ‘liang’}]

这个copy函数就是浅拷贝,把a的值浅拷贝给c,输出c的值发现和a是一模一样的

id(a)

140484710365256

id(b)

140484710365256

id(c)

140484717979336

分别把a,b,c的地址空间id查出来可以看到,a和c是不一样的,这就是浅拷贝的本质,是对父对象的拷贝,相当于b是a的备份,a和b占用的地址空间是不一样的。

a.append(‘d’)

a

[1, 2, 3, 4, [‘a’, ‘b’, ‘c’], {‘name’: ‘liang’}, ‘d’]

b

[1, 2, 3, 4, [‘a’, ‘b’, ‘c’], {‘name’: ‘liang’}, ‘d’]

c

[1, 2, 3, 4, [‘a’, ‘b’, ‘c’], {‘name’: ‘liang’}]

所以在对对象a执行append操作的时候,就会看到,c的值不会变的,因为操作的是两个不一样的地址空间。

a[4].append(‘d’)

a

[1, 2, 3, 4, [‘a’, ‘b’, ‘c’, ‘d’], {‘name’: ‘liang’}, ‘d’]

c

[1, 2, 3, 4, [‘a’, ‘b’, ‘c’, ‘d’], {‘name’: ‘liang’}]

id(a[4])

140484710449416

id(c[4])

140484710449416

但是对对象a的其中一个元素执行append()操作的时候,就会出现,c里面对应的元素还是会跟着变化的。通过查看地址空间的id可以看到,虽然a,c两个对象占用的地址空间不一样,但是c是a的浅拷贝,c元对象里面的元素仍然和a对象里面的元素占用一样的地址空间【例如上面的a[4]和c[4]】

下面我们用深拷贝:

d = copy.deepcopy(a)

d

[1, 2, 3, 4, [‘a’, ‘b’, ‘c’, ‘d’], {‘name’: ‘liang’}, ‘d’]

a[4].append(‘e’)

a

[1, 2, 3, 4, [‘a’, ‘b’, ‘c’, ‘d’, ‘e’], {‘name’: ‘liang’}, ‘d’]

d

[1, 2, 3, 4, [‘a’, ‘b’, ‘c’, ‘d’], {‘name’: ‘liang’}, ‘d’]

id(a[4])

140484710449416

id(d[4])

140484710365832



我们还是对a进行深拷贝为d,然后还是对a[4]元素进行append操作,发现c对象的c[4]元素并没有发生改变,通过查看这个元素的id可以看到,两个元素的地址空间是不一样的,所以这才是真正意义上的完全的拷贝。简单的来说就是,浅拷贝只是增加了一个指针指向已经存在的内存,而深拷贝就是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存,也就是说,在浅拷贝情况下,不同引用指向的是同一块内存,改其中一个引用,那么其他引用也会跟着改变 ,浅拷贝就是对整个父对象的拷贝。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python 对象 linux