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

Python语言中的引用和拷贝

2016-05-24 20:41 211 查看
本文对Python语言中的引用和拷贝的概念进行一个梳理。Python中赋值就是引用操作,而拷贝又分为浅拷贝、深拷贝两种方式。

下面我们来了解一下。

1、引用

python中赋值符号“=”两边的对象是同一个对象,左边的对象可以看成是右边对象的一个引用。举例:

>>> a=[1,2,'a','b']
>>> b=a
>>> a
[1, 2, 'a', 'b']
>>> b
[1, 2, 'a', 'b']
>>> a.append('c')
>>> a
[1, 2, 'a', 'b', 'c']
>>> b
[1, 2, 'a', 'b', 'c']
>>> a is b
True


说明:

从例子中可看到,a的值的变化会导致b的值也会变化,因为他们是同一个对象,共享同一块内存地址,b是a的引用。

判断两个变量是否是同一个对象的方法是用is,返回True则代表两个变量是同一个对象。

总结:

赋值是将一个对象的地址赋值给一个变量,让变量指向该地址( 旧瓶装旧酒 )。

2、拷贝

对象的拷贝是根据源对象生成一个新的对象,占用不同的内容存空间。一个对象值的变化,不会影响另外一个对象的值。拷贝又分潜拷贝和深拷贝。

2.1、潜拷贝

python中的copy模块可以实现对象的浅拷贝。什么是浅拷贝?举个例子来说明:

>>> import copy
>>> a=[[1,2],['a','b']]
>>> b=copy.copy(a)
>>> b is a
>>> False
>>> a.append('c')
>>> a
[[1, 2], ['a', 'b'], 'c']
>>> b
[[1, 2], ['a', 'b']]
>>> a[0].append(3)
>>> a
[[1, 2, 3], ['a', 'b'], 'c']
>>> b
[[1, 2, 3], ['a', 'b']]
>>> a[0] is b[0]
>>> True


说明:

通过例子可以看到通过copy模块的copy方法,根据对象a生成了一个新对象b,这一点可以通过is表达式的结果证明。

a.append(‘c’)之后,发现a和b的值不一样了,这是因为a和b指向两个不同的地址。对a的值的修改不会影响b的值。

但是a[0].append(3)之后,a[0]和b[0]却是一样的。这就是浅拷贝的效果。因为a[0] 和b[0]还是指向同一个地址。

总结:

浅拷贝是在另一块地址中创建一个新的变量或容器,但是容器内的元素的地址均是源对象的元素的地址的拷贝。也就是说新的容器中指向了旧的元素( 新瓶装旧酒 )

2.2、深拷贝

python的copy模块的deepcopy函数可以实现深拷贝。

还是以上面的例子为例。

>>> import copy
>>> a=[[1,2],['a','b']]
>>> b=copy.deepcopy(a)
>>> a is b
False
>>> a[0] is b[0]
False
>>> a.append('c')
>>> a
[[1, 2, 3], ['a', 'b'], 'c']
>>> b
[[1, 2], ['a', 'b']]
>>> a[0].append(3)
>>> a
[[1, 2, 3], ['a', 'b']]
>>> b
[[1, 2], ['a', 'b']]


说明:

由于b是a的深拷贝,所以a对象和b对象的内存地址不同,a对象和b对象包含的底层对象(a[0]a[1]b[0]b[1])内存地址也不同。

对a对象的值的改变不会影响b对象的值,对a对象的底层对象的值的改变也不会影响b的底层对象的值。

总结:

深拷贝是在另一块地址中创建一个新的变量或容器,同时容器内的元素的地址也是新开辟的,仅仅是值相同而已,是完全的副本。也就是说( 新瓶装新酒 )。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: