个人认为可变对象和深浅拷贝是未来编程首要注意的事情,毕竟如果是这个上面出现bug应该比较难察觉。
首先贴概念:
在python中,拷贝就是为对象添加新的名字。
浅拷贝:只复制引用,而不复制对象本身的情况。
深拷贝:复制内容,而非简单复制引用(可使用copy模块中的deepcopy函数)
我们只需要记住一点,python中的list列表是可变对象,当列表被封装(如list1 = list1 + [list2]或者list1.append(list2))之后,作为其他列表的一个部分时,其会随着相同引用对象的改变而改变;相反如果列表被拆分了(如list1 = list1 + list2或者list1.extend(list2)),我们就不用担心里头的元素会随着其他对象的改变而发生变化。
下面给出运行实例:
list1 = [1,2,3] list2 = [5,6,7] list1.append(list2) # 列表进行了封装,仅改变list1本身 list2[-1] = 100 print list1 ## 对应结果 print list2 ## list1 = [1,2,3] list2 = [5,6,7] list1 = list1 + [list2] # 列表进行了封装,并生成新列表对象 list2[-1] = 100 print list1 ## print list2 ## list1 = [1,2,3] list2 = [5,6,7] list1 = list1 + list2 # 生成新列表对象 list2[-1] = 100 print list1 ## print list2 ## list1 = [1,2,3] list2 = [5,6,7] list1.extend(list2) # 仅改变list1本身 list2[-1] = 100 print list1 ## print list2 ##
结果
# [1, 2, 3, [5, 6, 100]] # [5, 6, 100] # [1, 2, 3, [5, 6, 100]] # [5, 6, 100] # [1, 2, 3, 5, 6, 7] # [5, 6, 100] # [1, 2, 3, 5, 6, 7] # [5, 6, 100]
这里还要介绍一下python里头的两个相等的判断函数:
is: 判断两个name是否引用的同一对象,使用方法 list2 is list3,返回true/false
== : 判断两个name对引用的value是否一致,使用方法 list2 == list3
list1 = [1,2,3] list2 = list1[:] #相当于深复制,生成一个新对象 list3 = list1 # 浅复制,引用相同对象,可节省储存空间 print list1 is list2 print list1 == list2 print list1 is list3 print list1 == list3
结果为
# False # True # True # True
最后给出一个防不胜防的例子,这个例子里头一个封装好的列表并没有被其他name引用,而且copyLst采用了复制操作,但是由于封装的原因,所有Lst中的封装列表元素都发生了变化,大家自己感受下= =
strLst = ["hi", "mom", "dad", ["grandma", "grandpa"]] newLst = strLst copyLst = strLst[:] strLst[0] = "bye" newLst[1] = "mother" copyLst[2] = "father" copyLst[-1][0] = "nanna" print strLst print newLst print copyLst
运行结果
# ['bye', 'mother', 'dad', ['nanna', 'grandpa']] # ['bye', 'mother', 'dad', ['nanna', 'grandpa']] # ['hi', 'mom', 'father', ['nanna', 'grandpa']]
以后大家编程时遇到列表里头嵌套有封装列表的,创建其他name之后需要小心再小心啦~解决方法就是对于重要的全局变量采用不可变对象比如元组tuple,而对不可变对象进行操作,每次都会创建一个新的对象哦~相反,对于可变对象来说,改变该对象或者创建一个新对象都是有可能发生的(比如list.append(9)是改变原对象而list = list + [9]则是创建了一个新对象)。
Leave A Comment