目标:
深拷贝源码分析
0 深浅拷贝基础
关键:
1 深拷贝:拷贝了对象所有元素,包含嵌套元素。是与原来对象无关的全新对象。无关性。
2 浅拷贝: 创建新对象,但新对象中各个元素是原对象对应各个元素的引用。
3 举例如下:
a = [1,[2,3]]
c = copy.copy(a)
那么a与c虽然是两个不同对象(id(a) != id(c)),但是a与c中各个元素是相同的(例如id(a[0]) = id(c[0]) , id[a[1]]=id(c[1]))
那么就是说:
例1: a.append(5)会导致a变成[1,[2,3],5],但由于a与c的地址不同,c并不会有变化。
例 2: a[1].append(6)会导致a变成[1,[2,3,6]],同样也会使得c变成[1,[2,3,6]],因为a[1] 与 c[1]地址相同,a[1]和c[1]实际是同一个对象。
总结:
深浅拷贝都是创建新的对象。但深拷贝包含了嵌套拷贝,拷贝后的对象与原对象无关。
浅拷贝中的每个元素和原对象每个元素相同,如果对元素操作,会使得浅拷贝对应元素发生变化。
参考:
https://www.cnblogs.com/xueli/p/4952063.html
https://www.cnblogs.com/huangbiquan/p/7795152.html
https://blog.csdn.net/w494675608/article/details/82114798
1 主入口
这里使用自己编写的一个demo作为总入口
import copy
def use_copy():
a = [1, [2, 3]]
b = copy.copy(a)
c = copy.deepcopy(a)
assert (id(a) != id(b))
for i, value in enumerate(a):
assert (id(a[i] == id(b[i])))
a.append(5)
assert b == [1, [2, 3]]
assert c == [1, [2, 3]]
a[1].append(6)
assert b == [1, [2, 3, 6]]
assert c == [1, [2, ]]
1.1 进入
E:\developSoftware\python27\Lib\copy.py
代码如下:
def copy(x):
"""Shallow copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
"""
cls = type(x)
copier = _copy_dispatch.get(cls)
if copier:
return copier(x)
copier = getattr(cls, "__copy__", None)
if copier:
return copier(x)
reductor = dispatch_table.get(cls)
if reductor:
rv = reductor(x)
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor:
rv = reductor(2)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
rv = reductor()
else:
raise Error("un(shallow)copyable object of type %s" % cls)
return _reconstruct(x, rv, 0)
分析:
x: <type 'list'>: [1, [2, 3]]
cls: <type 'list'>
_copy_dispatch:
<type 'dict'>: {<type 'instance'>: <function _copy_inst at 0x0000000003C394A8>, <type 'dict'>: <function _copy_with_constructor at 0x0000000003C393C8>, <type 'ellipsis'>: <function _copy_immutable at 0x0000000003C39358>, <type 'long'>: <function _copy_immutable at 0x0000000003C39358>, <type 'type'>: <function _copy_immutable at 0x0000000003C39358>, <type 'builtin_function_or_method'>: <function _copy_immutable at 0x0000000003C39358>, <type 'complex'>: <function _copy_immutable at 0x0000000003C39358>, <type 'set'>: <function _copy_with_constructor at 0x0000000003C393C8>, <type 'NoneType'>: <function _copy_immutable at 0x0000000003C39358>, <type 'xrange'>: <function _copy_immutable at 0x0000000003C39358>, <type 'int'>: <function _copy_immutable at 0x0000000003C39358>, <type 'unicode'>: <function _copy_immutable at 0x0000000003C39358>, <type 'weakref'>: <function _copy_immutable at 0x0000000003C39358>, <type 'classobj'>: <function _copy_immutable at 0x0000000003C39358>, <type 'list'>: <function _copy_with_constructor at 0x0000000003C393C8>, <type 'tuple'>: <function _copy_immutable at 0x0000000003C39358>, <type 'function'>: <function _copy_immutable at 0x0000000003C39358>, <type 'bool'>: <function _copy_immutable at 0x0000000003C39358>, <type 'float'>: <function _copy_immutable at 0x0000000003C39358>, <type 'code'>: <function _copy_immutable at 0x0000000003C39358>, <type 'frozenset'>: <function _copy_immutable at 0x0000000003C39358>, <type 'str'>: <function _copy_immutable at 0x0000000003C39358>}
copier:
<function _copy_with_constructor at 0x0000000003C393C8>
1.2 进入
def _copy_with_constructor(x): # 浅拷贝可变对象,需要重新创建一个新的对象
return type(x)(x)
另外还有一个:
def _copy_immutable(x): # 浅拷贝不可变对象就返回自己
return x
分析:
x: <type 'list'>: [1, [2, 3]]
其中:
type(x)应该就是list
所以这里类似list([1, [2,3]])
直接拷贝
2 总结
浅拷贝根据待拷贝对象的类型,对不可改变对象x直接返回x自己,
对于可变对象x,则用type(x)(x)重新创建一个新的对象。
参考:
copy.copy()源码
https://www.2cto.com/kf/201405/302337.html