本文适合阅读对象:已学完Python基础课程,并能熟练使用Python基本用法编程。如果还有一些其他语言的基础最好不过了,如果没有Python基础或者正在学习中,请点击以下链接:
Python基础教程
一、对象比较:is与==
达恩·巴德尔在令其声名大噪的《Python T'ricks》一书中,举了一个经典的双胞胎猫的例子,邻居家有一对双胞胎猫,两只猫看起来完全相同,除非个性上的小癖好,单从外表无法区分,尽管看起来完全一样,但它们依然是两只不同的猫。因此,大家就知道,相等和相同二者之间是有所区别的。
==操作符是比较相等性的,用==来比较那两只猫,得到的答案是“两只猫是一样的”;is操作符是比较相同性,用is来比较那两只猫,得到的答案是“两只猫不是同一只猫”。
a=['a','b','c']
b=list(a)
print(a==b)
def test(t):
return a is t
print(test(b))
c = a
print(test(c))
结果如下:
print(a==b)的结果是True,没毛病,二者相等;a is b的结果是False,原因是它们没有指向一个对象,对已有列表d调用list(),创建了一个名为b的副本;a is c的结果是True,原因是它们指向同一个对象。
二、克隆对象
由上面的例子大家发现,Python中的赋值语句不会创建对象的副本,而只是将名字绑定到对象上。但有些场景下,大家需要用到对象的副本,以便修改副本时不会改动本体。那么如何在Python中复制或克隆对象呢?先来看看Python的内置容器(列表、字典、集合)如何复制,如下所示:
new_list = list(old_list)
new_dict = dict(old_list)
new_set = set(old_list)
但是用这种方法无法复制自定义的对象,并且最重要的是这种方法只创建浅副本。浅复制和深复制之间有重要区别,特别对于像列表、字典、集合这样的复合对象而言。
1. 浅复制是指构建一个新的容器对象,然后填充原对象中子对象的引用。本质上浅复制只执行一层,复制过程不会递归,不会创建子对象的副本。
2. 深复制是递归复制,首先构造一个新的容器对象,然后递归地填充原始对象中子对象的副本,这种方式会遍历整个对象树,以此创建了与原对象及其所有子项完全独立的副本。
三、浅复制
xs = [[1,2,3],[4,5,6],[7,8,9]]
ys = list(xs)#浅复制
ys现在是一个新的独立对象,与xs有相同内容,大家可以打印查看这两个对象确认一下:
但是由于前面只是创建了原列表的浅副本,所以ys仍然含有xs子对象的引用。这些子对象没有复制,只是在ys中再次引用。因此在修改xs中的子对象时,这些改动也会被反映在ys中:因为两个列表共享相同的子对象。这个副本是仅含有一层的浅复制。
xs[1][0] = 'X'
print(xs)
print(ys)
四、深复制
修改上面的列表浅复制示例,这次使用copy模块中定义的deepcopy()函数创建深副本:
import copy
xs = [[1,2,3],[4,5,6],[7,8,9]]
zs = copy.deepcopy(xs)#深复制
在查看xs及使用copy.deepcopy()创建的副本zs时,会发现和前面的示例相同,它们看起来都一样:
但如果修改原对象xs中的某个子对象,则会发现不同上面示例,这些修改不会影响深副本zs。现在原对象和副本是完全独立的。复制过程中递归复制了xs,包括它所有的子对象:
xs[1][0] = 'X'
print(xs)
print(zs)
大家看出来了不同了吗,顺便说一句,还可以使用copy模块copy.copy()函数创建对象的浅副本。
发表评论 取消回复