• Python正课14 —— 深浅Copy


    本文内容皆为作者原创,如需转载,请注明出处:https://www.cnblogs.com/xuexianqi/p/12450407.html

    一:引子

    如果把一个列表的值引用给另一个列表,它们的值和id是否相等?

    l1 = ['xxq',18,'male'] 		#定义列表l1
    l2 = l1		#把l1的值引用给l2
    
    print(l1)	#输出l1的内容
    print(l2)	#输出l2的内容
    print(id(l1))	#输出l1的id
    print(id(l2))	#输出l2的id
    
    ['xxq', 18, 'male']
    ['xxq', 18, 'male']
    58970184
    58970184
    

    这里可以看出,他们输出的内容完全相等。

    01


    l1 = ['xxq',18,'male']
    l2 = l1
    l1[0] = 'qwe'	#将l1的第一个值改变
    
    print(l1)
    print(l2)
    print(id(l1))
    print(id(l2))
    
    ['qwe', 18, 'male']
    ['qwe', 18, 'male']
    17354824
    17354824
    

    这里可以看出:二者分隔不开,l1改l2也跟着改,因为指向的就是同一个地址。

    02

    但是,如果想要把2个列表完全独立开,互不影响,该怎么操作呢?

    二:浅Copy

    浅Copy:是把原列表第一层的内存地址不加区分完全copy一份给新列表

    小白鼠实验:

    l1 = ['xxq',18,'male']
    l3 = l1.copy()
    
    print(l1)
    print(l3)
    print(id(l1))
    print(id(l3))
    
    ['xxq', 18, 'male']
    ['xxq', 18, 'male']
    30396488
    60089832
    

    由此可以看出:l3拷贝了l1的值,但是l3和l1的id是不同的。

    03


    实验1:

    对于不可变类型的赋值,都是产生了新值,让原列表的索引指向新的内存地址,并不会影响新列表。

    l1 = ['xxq',18,'male']
    l3 = l1.copy()
    l1[0] = 'asd'
    l3[0] = 'zxc'
    
    
    print(l1)
    print(l3)
    print(id(l1))
    print(id(l3))
    print(id(l1[0]),id(l1[1]),id(l1[2]))
    print(id(l3[0]),id(l3[1]),id(l3[2]))
    
    ['asd', 18, 'male']
    ['zxc', 18, 'male']
    11718728
    13362664
    13484608 1494739136 13484576
    13484640 1494739136 13484576
    
    Process finished with exit code 0
    
    

    实验2:

    但对于可变类型,我们可以改变可变类型中包含的值,但内存地址不变即原列表的索引指向仍然指向原来的内存地址,于是新列表也跟着一起受影响,如下:

    这个例子中,l4浅Copy了l1,可以看出l1和l4列表内的元素内存地址相同,列表内存地址不同

    l1 = ['xxq',18,[1,2]]
    
    l4 = l1.copy()
    
    print(l1)
    print(l4)
    print(id(l1))
    print(id(l4))
    print(id(l1[0]),id(l1[1]),id(l1[2]),id(l1[2][0]),id(l1[2][1]))
    print(id(l4[0]),id(l4[1]),id(l1[2]),id(l4[2][0]),id(l4[2][1]))
    
    ['xxq', 18, [10, 2]]
    ['xxq', 18, [10, 2]]
    11724264
    11724968
    57259360 1494739136 55889992 1494738864 1494738880
    57259360 1494739136 55889992 1494738864 1494738880
    

    04

    这个例子中,l4浅Copy了l1,并且l1和l4列表中的列表元素值改变,可以看出l1和l4列表内的元素内存地址相同,列表内存地址不同

    l1 = ['xxq',18,[1,2]]
    
    l4 = l1.copy()
    
    l1[2][0] = 20
    l4[2][1] = 10
    
    print(l1)
    print(l4)
    print(id(l1))
    print(id(l4))
    print(id(l1[0]),id(l1[1]),id(l1[2]),id(l1[2][0]),id(l1[2][1]))
    print(id(l4[0]),id(l4[1]),id(l1[2]),id(l4[2][0]),id(l4[2][1]))
    
    ['xxq', 18, [20, 10]]
    ['xxq', 18, [20, 10]]
    19654120
    19654824
    19777088 1494739136 18272328 1494739168 1494739008
    19777088 1494739136 18272328 1494739168 1494739008
    

    05

    综合实验1和实验2可以得出,要想copy得到的新列表与原列表的改操作完全独立开

    必须有一种可以区分开可变类型与不可变类型的copy机制,这就是深copy

    三:深Copy

    要使用深Copy,要先导入库:

    import copy
    

    然后使用

    import copy
    list1=[
        'egon',
        'lxx',
        [1,2]
    ]
    
    list3=copy.deepcopy(list1)
    # print(id(list1))
    # print(id(list3))
    # print(list3)
    
    #          不可变        不可变        可变
    # print(id(list1[0]),id(list1[1]),id(list1[2]))
    # print(id(list3[0]),id(list3[1]),id(list3[2]))
    '''
    4497919088 4498367856 4498449216
    4497919088 4498367856 4498595328
    '''
    # print(list3)
    # print(id(list1[2][0]),id(list1[2][1]))
    # print(id(list3[2][0]),id(list3[2][1]))
    
    list1[0]='EGON'
    list1[1]='LXX'
    
    list1[2][0]=111
    list1[2][1]=222
    # print(list1)
    
    print(list3)
    
  • 相关阅读:
    解决Vss链接问题清除Windows共享登录的用户名密码记录(转)
    C# 激活正在运行的程序
    Log4Net 使用方法
    对Javascript闭包的一些理解
    根据数据库获取表名集合,根据表名获取字段信息
    C#引用类型和值类型的区别(转)
    c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast
    理解VC工程文件类型
    MFC中的UpdateData()
    字节对齐
  • 原文地址:https://www.cnblogs.com/xuexianqi/p/12450407.html
Copyright © 2020-2023  润新知