深拷贝和浅拷贝
1、对象的赋值
对象的赋值实际上是对象之间的引用:当创建一个对象,然后将这个对象赋值给另外一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用。
当对对象做赋值或者是参数传递或者作为返回值的时候,总是传递原始对象的引用,而不是一个副本。如下所示:
>>> aList = ["kel","abc",123] >>> bList = aList >>> bList.append("add") >>> aList ['kel', 'abc', 123, 'add'] >>> bList ['kel', 'abc', 123, 'add'] >>> id(aList),id(bList) (140041880705648, 140041880705648) |
2、对象的复制
当你想修改一个对象,而且让原始的对象不受影响的时候,那么就需要使用到对象的复制,对象的复制可以通过三种方法实现:
a、 使用切片操作进行拷贝--slice operation
b、 使用工厂函数进行拷贝,list/dir/set--factoryfunction
c、 copy.copy()--use copymodule
在复制的时候,使用的是浅拷贝,复制了对象,但是对象中的元素,依然使用引用。
如下所示:
>>> person = ["name",["savings",100.00]] >>> hubby = person[:] #切片操作 >>> wifey = list(person) #使用工厂函数 >>> [id(x) for x in person,hubby,wifey] [139797546486384, 139797546556592, 139797546557240] >>> [id(x) for x in hubby] [139797546838128, 139797546485808] >>> [id(x) for x in wifey] [139797546838128, 139797546485808] >>> hubby[0] = "kel" >>> wifey[0] = "jane" >>> hubby[1][1] = 50.0 >>> [id(x) for x in hubby,wifey] [139797546556592, 139797546557240] >>> [id(x) for x in hubby] [139797546592368, 139797546485808] >>> [id(x) for x in wifey] [139797546592416, 139797546485808] >>> hubby ['kel', ['savings', 50.0]] >>> wifey ['jane', ['savings', 50.0]] |
在使用浅拷贝的时候,发现引用的id都是相同的,但是字符串的id却发生了变化,是因为在python中,字符串是不可变的,从而在每次进行修改的时候,都是新建一个对象,从而引用发生了变化。
在不可变类型中,数字和字符串都是不可变类型,从而在每次修改的时候,都是新创建一个对象。
3、模块
核心模块:copy
浅拷贝和深拷贝的操作都可以在copy模块中找到,其实copy模块中只有两个函数可用,copy()进行浅拷贝操作,而deepcopy()进行深拷贝操作
4、拷贝的警告
第一:非容器类型(比如数字,字符串和其他原子类型的对象,例如代码,类型和xrange对象等)没有拷贝一说,浅拷贝是完全用切片操作来完成的。
第二:如果元组变量只包含原子类型对象,那么深拷贝将不会进行。
>>> aList = [1,"kel",[1,2,3]] >>> import copy >>> deepList = copy.deepcopy(aList) >>> deepList[2].append("kel") >>> aList [1, 'kel', [1, 2, 3]] >>> deepList [1, 'kel', [1, 2, 3, 'kel']] |