今天电面遇到Python中浅拷贝和深拷贝的区别,平时不经常用当然不知道了,回来就补个课。
先举个非常常见的例子:
import copy
list1 = [1, 2, 3, ['a', 'b']]
list2 = list1
list3 = copy.copy(list1)
list4 = copy.deepcopy(list1)
list1.append(5)
list1[3].append('c')
print 'list1: ', list1
print 'list2: ', list2
print 'list3: ', list3
print 'list4: ', list4
#######################################
list1: [1, 2, 3, ['a', 'b', 'c'], 5]
list2: [1, 2, 3, ['a', 'b', 'c'], 5]
list3: [1, 2, 3, ['a', 'b', 'c']]
list4: [1, 2, 3, ['a', 'b']]
########################################
从上面这个例子可以看出,如果浅拷贝一个列表,那么系统会新建一个列表,它的每个元素指向原来那个列表的每个元素(就像C语言里的指针数组),输出的时候会把各个元素指向的元素内容显示出来。所以当list1追加了元素5后,list3并没有显示出来,因为list3中并没有指向这个新元素的元素;但是list1[3]追加了'c',list3也追加了'c',是因为list3中有指向'c'所在列表的元素。
而对于深拷贝来说,无论list1作何改变,list4都不会随之改变,是因为深拷贝是新建一个列表,把原来列表的内容原封不动拷过来,是的新的列表和原来的列表一模一样,这是对象资源的拷贝。
可以再参考下面两个例子。
1.浅拷贝
========
import copy
class MyClass:
def __init__(self, name):
self.name = name
def __cmp__(self, other):
return cmp(self.name, other.name)
a = MyClass('a')
myList = [a]
dup_shallow = copy.copy(myList)
print 'myList: ', myList
print 'dup_shallow: ', dup_shallow
print 'dup_shallow is myList: ', (dup_shallow is myList)
print 'dup_shallow == myList: ', (dup_shallow == myList)
print 'dup_shallow[0] is myList[0]: ', (dup_shallow[0] is myList[0])
print 'dup_shallow[0] == myList[0]', (dup_shallow[0] == myList[0])
######################################################################
myList: [<__main__.MyClass instance at 0x0000000002264408>]
dup_shallow: [<__main__.MyClass instance at 0x0000000002264408>]
dup_shallow is myList: False # copy又新建了一个列表,dup_shallow中的元素指向myList中的元素
dup_shallow == myList: True # 两个列表指向同一块内存地址的内容,则两个列表的内容必定相等
dup_shallow[0] is myList[0]: True # 两个对象指向的内存地址相同
dup_shallow[0] == myList[0] True
######################################################################
2.深拷贝
import copy
class MyClass:
def __init__(self, name):
self.name = name
def __cmp__(self, other):
return cmp(self.name, other.name)
a = MyClass('a')
myList = [a]
dup_deep = copy.deepcopy(myList)
print 'myList: ', myList
print 'dup_deep: ', dup_deep
print 'dup_deep is myList: ', (dup_deep is myList)
print 'dup_deep == myList: ', (dup_deep == myList)
print 'dup_deep[0] is myList[0]: ', (dup_deep[0] is myList[0])
print 'dup_deep[0] == myList[0]', (dup_deep[0] == myList[0])
################################################################
myList: [<__main__.MyClass instance at 0x0000000002264408>]
dup_deep: [<__main__.MyClass instance at 0x0000000002264308>]
dup_deep is myList: False
dup_deep == myList: True # 两个列表虽然指向不同的内存地址,但是内存地址中存储的内容相同
dup_deep[0] is myList[0]: False # 两个对象的内存地址不同
dup_deep[0] == myList[0] True
#################################################################