Python中的复制操作及copy模块中的浅拷贝与深拷贝方法

1089次阅读  |  发布于5年以前

程序中常常需要复制一个对象, 按思路应该是这样的


    a = [1, 2, 3]
    b = a

    # [1, 2, 3]
    print b 

已经复制好了,但是现在得改变一下第一个元素的值把它改成5


    b[0] = 5 

    # [5, 2, 3]
    print b 

    # [5, 2, 3]
    print a 

我改变了b的第一个元素的值,但是a的值也改变了,这是因为python中的=是引用.a和b指向的是相同的列表,所以改变列表会出现以上的结果.

解决方法是切片操作


    a = [1, 2, 3]
    b = a[:]
    b[0] = 4

    # [1, 2, 3]
    # [4, 2, 3]
    print a
    print b

但是在嵌套列表的时候呢,试一试


    a = [[1,2,3], 4, 5]
    b = a[:]
    b[1] = 0 

    # [[1,2,3], 4, 5]
    # [[1,2,3], 0, 5]
    print a
    print b

恩!没什么问题,在试一试嵌套列表元素


    a = [[1,2,3], 4, 5]
    b = a[:]
    b[0][0] = 5

    # [[5,2,3], 4, 5]
    # [[5,2,3], 4, 5]
    print a
    print b
    b = a[:]

a的值还是改变了,切片复制只对该对象进行拷贝不会对子元素进行拷贝

copy 模块

copy模块用于对象的拷贝操作。该模块非常简单,只提供了两个主要的方法: copy.copy 与 copy.deepcopy ,分别表示浅复制与深复制。什么是浅复制,什么是深复制,网上有一卡车一卡车的资料,这里不作详细介绍。复制操作只对复合对象有效。用简单的例子来分别介绍这两个方法。

浅复制只复制对象本身,没有复制该对象所引用的对象。


    #coding=gbk
    import copy
    l1 = [1, 2, [3, 4]]
    l2 = copy.copy(l1)
    print l1
    print l2
    l2[2][0] = 50
    print l1
    print l2

结果:


    [1, 2, [3, 4]]
    [1, 2, [3, 4]]
    [1, 2, [50, 4]]
    [1, 2, [50, 4]]

同样的代码,使用深复制,结果就不一样:


    import copy
    l1 = [1, 2, [3, 4]]
    l2 = copy.deepcopy(l1)
    print l1
    print l2
    l2[2][0] = 50
    print l1
    print l2

结果:


    [1, 2, [3, 4]]
    [1, 2, [3, 4]]
    [1, 2, [3, 4]]
    [1, 2, [50, 4]]

改变copy的默认行为

在定义类的时候,通过定义copydeepcopy方法,可以改变copy的默认行为。下面是一个简单的例子:


    class CopyObj(object):
      def __repr__(self):
        return "CopyObj"

      def __copy__(self):
        return "Hello"
    obj = CopyObj()
    obj1 = copy.copy(obj)
    print obj
    print obj1

结果:


    CopyObj
    Hello

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8