python 64式: 第46式、浅拷贝源码分析

目标:
深拷贝源码分析

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值