zoukankan      html  css  js  c++  java
  • 我的Python学习笔记(二):浅拷贝和深拷贝

    在Python中,对象赋值,拷贝(浅拷贝和深拷贝)之间是有差异的,我们通过下列代码来介绍其区别

    一、对象赋值

    对象赋值不会复制对象,它只会复制一个对象引用,不会开辟新的内存空间

    如下例所示,将test赋值给copytest后,test和copytest的id值相同,test和copytest指向的是同一个list,所以当test的值改变时,copytest的值也相应改变

    test = ["test", 18, ["python","java"]]
    copytest = test
    print(test)         # ['test', 18, ['python', 'java']]
    print(copytest)     # ['test', 18, ['python', 'java']]
    print(id(test))     # 4559314816
    print(id(copytest)) # 4559314816
    
    test[0] = "changetest"
    test[2].append("css")
    print(test)         # ['changetest', 18, ['python', 'java', 'css']]
    print(copytest)     # ['changetest', 18, ['python', 'java', 'css']]
    print(id(test))     # 4559314816
    print(id(copytest)) # 4559314816

    二、拷贝

    对于复合对象,如果有时我们不想因为其中一个对象改变而改变另外一个对象的值,我们可以使用Python的copy模块。

    copy模块中包含如下两个方法:

     

    copy.copy(x)方法返回x的浅拷贝,copy.deepcopy(x)方法返回x的深拷贝

    我们来理解下浅拷贝和深拷贝的区别:

    浅拷贝和深拷贝的区别只与复合对象有关系(复合对象就是对象中包含其他对象,例如list和其他实例类)

    • 浅拷贝构造了一个新的复合对象,然后(尽可能)把原来的对象引用直接插入到新对象中
    • 深拷贝构造了一个新的复合对象,然后递归的将原对象中的内容进行复制,并插入新对象

      1、浅拷贝

    在下例中,浅拷贝会为copytest开辟新的内存空间,但copytest中的对象仍然是test中的对象引用,不会对其中的对象进行复制

    import copy
    
    test = ["test", 18, ["python","java"]]
    copytest = copy.copy(test)
    print(test)                     # ['test', 18, ['python', 'java']]
    print(copytest)                 # ['test', 18, ['python', 'java']]
    print(id(test))                 # 4484571008
    print(id(copytest))             # 4484611320
    print [id(x) for x in test]     # [4484554208, 140582137648080, 4484569424]
    print [id(x) for x in copytest] # [4484554208, 140582137648080, 4484569424]
    
    test[0] = "changetest"
    test[2].append("css")
    print(test)                     # ['changetest', 18, ['python', 'java', 'css']]
    print(copytest)                 # ['test', 18, ['python', 'java', 'css']]
    print(id(test))                 # 4484571008
    print(id(copytest))             # 4484611320
    print [id(x) for x in test]     # [4484554352, 140582137648080, 4484569424]
    print [id(x) for x in copytest] # [4484554208, 140582137648080, 4484569424]
    • test和copytest的id值不同,但copytest并没有将copy内的值重新拷贝一份,而是直接指向copy内的值。
    • 当执行test[0] = "changetest”时,test[0]重新指向字符串”changetest”,而copttest[0]仍然指向字符串”test”。
    • 当执行test[2].append("css”)时,更改了test[2]指向的list中的值,而test和copytest都指向此list,所以copytest也相应改变了

     注:字典的浅拷贝可以使用dict.copy(),list的浅拷贝可以使用slice截取整个list,例如:copied_list original_list[:]

      2、深拷贝:

    在下例中,深拷贝会为copytest开辟新的内存空间,并将test中的复合对象进行拷贝,并将其引用赋值给新copytest

    import copy
    
    test = ["test", 18, ["python","java"]]
    copytest = copy.deepcopy(test)
    print(test)                     # ['test', 18, ['python', 'java']]
    print(copytest)                 # ['test', 18, ['python', 'java']]
    print(id(test))                 # 4476972928
    print(id(copytest))             # 4477013240
    print [id(x) for x in test]     # [4476956224, 140706592084752, 4476971344]
    print [id(x) for x in copytest] # [4476956224, 140706592084752, 4477013312]
    
    test[0] = "changetest"
    test[2].append("css")
    print(test)                     # ['changetest', 18, ['python', 'java', 'css']]
    print(copytest)                 # ['test', 18, ['python', 'java']]
    print(id(test))                 # 4476972928
    print(id(copytest))             # 4477013240
    print [id(x) for x in test]     # [4476956512, 140706592084752, 4476971344]
    print [id(x) for x in copytest] # [4476956224, 140706592084752, 4477013312]
    • test和copytest的id值不同,copytest将test中的list重新拷贝了一份,并指向重新拷贝的list
    • 当执行test[0] = "changetest”时,test[0]重新指向字符串”changetest”,而copttest[0]仍然指向字符串”test”。
    • 当执行test[2].append("css”)时,更改了test[2]指向的list的值,但copytest和test指向的并不是同一个list,所以copytest并不受影响

    注:深拷贝存在两个问题:一个是递归拷贝可能导致递归循环,另一个是深拷贝会拷贝所有的对象,而有些可以复用的对象也会被重复拷贝,导致拷贝过多的情况

  • 相关阅读:
    HDU 2116 Has the sum exceeded
    HDU 1233 还是畅通工程
    HDU 1234 开门人和关门人
    HDU 1283 最简单的计算机
    HDU 2552 三足鼎立
    HDU 1202 The calculation of GPA
    HDU 1248 寒冰王座
    HDU 1863 畅通工程
    HDU 1879 继续畅通工程
    颜色对话框CColorDialog,字体对话框CFontDialog使用实例
  • 原文地址:https://www.cnblogs.com/semon-code/p/8231041.html
Copyright © 2011-2022 走看看