Python复制引用、浅拷贝、深拷贝

Python赋值引用、浅拷贝、深拷贝

 

############################ 直接引用 #############################
<<< a = [1,2,3,4]
<<< b = a
# 假设id(a)指向A,则id(b)也指向A,且值都为[1,2,3,4]
a = [4,5,6,7]
# a重新赋值,id指向B,
# 此时b依旧指向A和[1,2,3,4]
# 而a指向新地址B和[4,5,6,7]
​
a = [1,2,3,4]
b = a
a[0]=4
a[1]=5
a[2]=6
a[3]=7
# 通过索引更改a的值
# 此时a和b依旧指向原来的内存地址,但是值都更新为了[4,5,6,7]
########################## 浅复制 ###############################
a = [1,2,3,4]
b=a.copy()
# 假设id(a)指向A,则id(b)指向B
a[0]=0
# id(a)依旧指向A,但是值改变了
# id(b)地址和值都没变            不含子对象,a和b独立,此时为深复制
# 但是当a中包含子对象时,子对象在浅复制时就会采用 引 用 方式而不是完全复制。继续使用浅复制时就会造成内层子对象的不完全复制,改变一个变量,另一个也会随之改变
import copy
a=[1,2,3,4,[4,5,6,7]]
b=copy.copy(a)
# 假设id(a)指向A,则id(b)指向B,值都为[1,2,3,4,[4,5,6,7]]
​
a[4].append(100)
# id(a)依旧指向A,值变为[1,2,3,4,[4,5,6,7,100]]
# id(b)依旧指向B, 值也变为[1,2,3,4,[4,5,6,7,100]]
###################### 深复制(deepcopy)符合我们直观的“复制”,完全独立,互不影响。



  1. 直接赋值既不是浅拷贝也不是深拷贝,我和你本质是一样的,只是名字不一样而已。

    a = 1
    b = a
    >>> a
    1
    >>> b
    1
    b = 2 #复新值,你就走了,a仍旧保持初心。
    >>> b
    2
    a
    >>>1

    a = [1, 2, [3, 4]]
    b = a
    b[2][0] = 99
    b[1] = 88
    print(a) #a与b同,你变我也变
    print(b)
    [1, 88, [99, 4]]
    [1, 88, [99, 4]]

     

  2. 浅拷贝(包括copy,切片):拷贝父对象,不会拷贝对象的内部的子对象。只复制对象本身,没有复制该对象所引用的对象。a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象,是引用。

    • 浅拷贝,你变我也变!

      • a = [1, 2, [3, 4]] #有子对象,子对象引用,
        b = a  #a和b同
        b[2][0] = 99
        b[1] = 88 #浅复制,此时也就是深复制
        print(a)
        print(b)
        [1, 22, [99, 4]]
        [1, 22, [99, 4]]
    • 如果没有子对象,那么浅拷贝就和深拷贝一样了(你清一色的,完全复制,相互独立,你变关我屁事!)

      • a = [1, 2, 3] #你太简单了,我直接搞一份,深复制
        b = a.copy()
        b[0] = 333
        print(b)
        print(a)
        >>[333, 2, 3] #你变
        >>[1, 2, 3]   #我不变
        # 切片方法在没有其他对象情况下,和深拷贝一样
        a = [1,2,3]
        b = a[:] # 深拷贝,id(a)不等于id(b)
        b
        >> [1, 2, 3]
        b[0] = 99
        b
        >> [99, 2, 3] #b变
        a
        >> [1, 2, 3] #a不变

        #########################################################
        import copy
        t1 = [1, 2, [3, 4]]
        t2 = copy.copy(t1) # 浅拷贝,子对象采用引用,而不是浅复制
        t2[2][0] = 99 # 通过索引改变,所以子对象也会跟着改变
        print(t1)
        print(t2)
        [1, 2, [99, 4]]
        [1, 2, [99, 4]]
        #########################################################
        a = [1, 2, [3, 4]]
        b = a[:] #b=a.copy() 浅复制 此时b与a的id不同
        b[2][0] =99  #b通过索引更改值,子对象引用,大家一起变!
        b[1] = 88 #此处为浅复制,其实也就是深复制,你变!我不变!
        print(a)
        print(b)
        [1, 2, [99, 4]]
        [1, 88, [99, 4]]
  1. 深复制(deepcopy),不仅复制对象本身,同时也复制该对象所引用的对象。a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。是我们直观上真正意义的“复制”。

    • import copy
      a = [1, 2, 3]
      b =copy.deepcopy(a)
      b
      >> [1, 2, 3]
      b[0] = 99
      b
      >> [99, 2, 3]
      a
      >> [1,2,3]

      c = [1, 2, 3, [4,5,6]]
      d = copy.deepcopy(c)
      d
      >> [1, 2, 3, [4,5,6]]
      d[0] = 99
      d[3][0] = 88
      d
      >> [99, 2, 3, [88, 5, 6]]
      c
      >> [1, 2, 3, [4, 5, 6]]
posted @ 2020-04-13 13:36  小伙明明  阅读(302)  评论(0)    收藏  举报