Python 浅拷贝、深拷贝
1. 浅拷贝
2. 深拷贝
3. 拷贝的其它方式
1. 浅拷贝
浅拷贝是对于一个对象的顶层拷贝。
通俗的理解是:拷贝了引用,并没有拷贝内容。
1 >>> a = [1, 2, 3] 2 >>> b = a 3 >>> id(a) 4 13081224 5 >>> id(b) 6 13081224 7 >>> a.append(4) 8 >>> b 9 [1, 2, 3, 4]
2. 深拷贝
深拷贝是对一个对象所有层次(递归)的拷贝。
1 >>> import copy 2 >>> a = [1, 2, 3] 3 >>> b = copy.deepcopy(a) # 深拷贝 4 >>> id(a) 5 13098408 6 >>> id(b) # b和a已经不是指向同个对象 7 12966280 8 >>> a.append(4) 9 >>> a 10 [1, 2, 3, 4] 11 >>> b 12 [1, 2, 3]
进一步理解深拷贝:
>>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> c = [a, b] # 浅拷贝,对于列表c,创建了新的内存空间;但其中的a、b仅是引用 >>> c [[1, 2, 3], [4, 5, 6]] >>> a.append(7) >>> c [[1, 2, 3, 7], [4, 5, 6]] >>> >>> d = c >>> id(c) 13097064 >>> id(d) 13097064 >>> e = copy.deepcopy(c) # 深拷贝,e、a、b均创建了新的内存空间 >>> id(e) 12966280 >>> a.append(8) >>> a [1, 2, 3, 7, 8] >>> c [[1, 2, 3, 7, 8], [4, 5, 6]] >>> e [[1, 2, 3, 7], [4, 5, 6]] >>> f = copy.copy(c) # 浅拷贝,对于列表f,创建了新的内存空间;但其中的a、b仅是引用 >>> id(c) 13097064 >>> id(f) 13081128 >>> a.append(9) >>> a [1, 2, 3, 7, 8, 9] >>> c [[1, 2, 3, 7, 8, 9], [4, 5, 6]] >>> f [[1, 2, 3, 7, 8, 9], [4, 5, 6]]
deepcopy() 图示:
浅拷贝对不可变类型和可变类型的 copy 不同:
1 >>> a = [1, 2, 3] 2 >>> b = copy.copy(a) # 浅拷贝可变类型,会新创建对象 3 >>> id(a) 4 13097480 5 >>> id(b) 6 13097672 7 >>> a.append(4) 8 >>> a 9 [1, 2, 3, 4] 10 >>> b 11 [1, 2, 3] 12 >>> 13 >>> a = (1, 2, 3) 14 >>> b = copy.copy(a) # 浅拷贝不可变类型,仅拷贝引用 15 >>> id(a) 16 24029512 17 >>> id(b) 18 24029512
3. 拷贝的其它方式
切片
1 >>> a = "abc" 2 >>> b = a[:] # 不可变类型,浅拷贝 3 >>> id(a) 4 1280907951440 5 >>> id(b) 6 1280907951440 7 >>> 8 >>> a = [1, 2, 3] 9 >>> b = a[:] # 可变类型,深拷贝 10 >>> id(a) 11 1280908916552 12 >>> id(b) 13 1280908915784
列表、字典的copy方法
1 >>> a = {1: 2, 2: "a"} 2 >>> b = a.copy() # 深拷贝,创建新对象 3 >>> id(a) 4 23759080 5 >>> id(b) 6 23759040
有些内置函数可以生成拷贝
1 >>> a = [1, 2] 2 >>> b = list(a) # 拷贝可变类型,创建新对象 3 >>> id(a) 4 13097672 5 >>> id(b) 6 13213224 7 >>> a = dict(a=1, b=2) 8 >>> b = dict(a) # 拷贝可变类型,创建新对象 9 >>> id(a) 10 13107104 11 >>> id(b) 12 13106464 13 >>> a = (1, 2) 14 >>> b = tuple(a) # 拷贝不可变类型,仅拷贝引用 15 >>> id(a) 16 13159912 17 >>> id(b) 18 13159912