Python深浅拷贝

Python深浅拷贝

在python中,对象赋值实际上是对象的引用。当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用

针对该列表l1=['a','b','c',['d','e','f']]一般有三种方法,分别为:拷贝(赋值)、浅拷贝、深拷贝

注意:拷贝/浅拷贝/深拷贝都是针对可变类型数据而言的,id不变值可变,即在原值的基础上修改,则为可变数据类型;值变id也变,即重新申请一个空间放入新值,则为不可变数据类型。

一、拷贝(赋值)

如果l2是l1的拷贝对象,则l1内部的任何数据类型的元素变化,则l2内部的元素也会跟着改变,因为可变类型值变id不变。

lt = [1, 2, 3, 4, 5]
lt2 = lt
lt.append(6)

print(lt)

# 因为列表是可变类型, 所以lt的值变化,lt2值也会跟着变化
print(lt2)

print(id(lt))
print(id(lt2))

结果:
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]


2304711549576
2304711549576

拷贝

二、浅拷贝

如果l2是l1的浅拷贝对象,则l1内的不可变元素发生了改变,l2不变;如果l1内的可变元素发生了改变,则l2会跟着改变。

  1. 添加值不发生变化

    import copy
    
    lt = [100, 200, 300, [400, 500, 600]]
    lt2 = copy.copy(lt)
    
    # 没有变化情况
    lt.append(700)
    print(lt)
    print(lt2)
    

    结果:

    [100, 200, 300, [400, 500, 600], 700]
    [100, 200, 300, [400, 500, 600]]

  2. 添加值发生变化

    import copy
    
    lt = [100, 200, 300, [400, 500, 600]]
    lt2 = copy.copy(lt)
    
    # 变化情况
    print('id(lt)',id(lt))
    print('id(lt[0])', id(lt[0]))
    print('id(lt[1])', id(lt[1]))
    print('id(lt[2])', id(lt[2]))
    print('id(lt[3])', id(lt[3]))
    print('*' * 50)
    print('id(lt2)',id(lt2))
    print('id(lt2[0])', id(lt2[0]))
    print('id(lt2[1])', id(lt2[1]))
    print('id(lt2[2])', id(lt2[2]))
    print('id(lt2[3])', id(lt2[3]))
    
    print('*' * 50)
    lt[-1].append(700)
    print(lt)
    print(lt2)
    

    结果:(浅拷贝,lt和lt2的id不一样,lt[-1]和lt[-1]一样)

    id(lt) 1520433324744
    id(lt[0]) 140712889544624
    id(lt[1]) 140712889547824
    id(lt[2]) 1520433550832
    id(lt[3]) 1520433324680


    id(lt2) 1520715912264
    id(lt2[0]) 140712889544624
    id(lt2[1]) 140712889547824
    id(lt2[2]) 1520433550832
    id(lt2[3]) 1520433324680


    [100, 200, 300, [400, 500, 600, 700]]
    [100, 200, 300, [400, 500, 600, 700]]

    浅拷贝

三、深拷贝

如果l2是l1的深拷贝对象,则l1内的不可变元素发生了改变,l2不变;如果l1内的可变元素发生了改变,l2也不会变,即l2永远不会因为l1的变化而变化。


import copy

lt = [100, 200, 300, [400, 500, 600]]
lt2 = copy.deepcopy(lt)
print('id(lt)',id(lt))
print('id(lt[0])', id(lt[0]))
print('id(lt[1])', id(lt[1]))
print('id(lt[2])', id(lt[2]))
print('id(lt[3])', id(lt[3]))
print('*' * 50)

print('id(lt2)',id(lt2))
print('id(lt2[0])', id(lt2[0]))
print('id(lt2[1])', id(lt2[1]))
print('id(lt2[2])', id(lt2[2]))
print('id(lt2[3])', id(lt2[3]))
print('*' * 50)

lt.append(70)
print(lt)
print(lt2)

print("*" * 50)

lt2[-1].append(7000)
print(lt)
print(lt2)

结果:

id(lt) 1585269859016
id(lt[0]) 140712889544624
id(lt[1]) 140712889547824
id(lt[2]) 1585270085104
id(lt[3]) 1585269858952


id(lt2) 1585552380680
id(lt2[0]) 140712889544624
id(lt2[1]) 140712889547824
id(lt2[2]) 1585270085104
id(lt2[3]) 1585299572040


[100, 200, 300, [400, 500, 600], 70]
[100, 200, 300, [400, 500, 600]]


[100, 200, 300, [400, 500, 600], 70]
[100, 200, 300, [400, 500, 600, 7000]]

深拷贝

四、总结

  1. 拷贝:当lt2为lt的拷贝对象时, lt内可变类型变化,lt2变化;lt内的不可变类型变化,lt2变化(简单赋值)
  2. 浅拷贝:当lt2为lt的拷贝对象时,lt内可变类型变化,lt2变化;lt内不可变类型变化,lt2不变化(copy.copy())
  3. 深拷贝:当lt2为lt的拷贝对象时, lt内的可变类型变化,lt2不变化;lt内不可变类型变化,lt2不变化(copy.deepcopy())

注:拷贝/浅拷贝/深拷贝 只针对可变数据类型

在当下的阶段,必将由程序员来主导,甚至比以往更甚。
原文地址:https://www.cnblogs.com/randysun/p/11310170.html