• Python-浅拷贝和深拷贝


    一、引用、浅拷贝、深拷贝

    1、赋值:B = A,相当于为变量创建一个引用。A和B指向的是同一个地址,id(A)==id(B)

    2、浅拷贝: B = copy.copy(A)。只拷贝第一层元素,若A是嵌套的对象,B不会拷贝嵌套的对象,而是引用嵌套的对象。

          id(A) != id(B) ,修改A的第一层元素,B不会变

            id( A[x] ) == id( B[x] ),修改A中嵌套对象中的元素(第二层),B也会变

    3、深拷贝: B = copy.deepcopy(A)。修改A中的任何一个元素,不会影响B

          id(A) != id(B)

          若x所在元素是原子类型对象(如数字、字符串),id(A[x]) ==id(B[x]) ,修改A 的第一层元素,B不会变

          若x所在元素是容器对象(如list、dict),id(A[x]) != id(B[x]),修改A中嵌套对象中的元素(第二层),B也不会变

    二、对于原子类型对象(如数字、字符串),没有深拷贝一说 。所有的拷贝都是浅拷贝。修改原始数据都会开辟一个新的内存地址,而不会影响到拷贝的对象

    A = 'hello'
    B = A
    C = copy.copy(A)
    D = copy.deepcopy(A)
    print('id(A) = %d, id(B) = %d, id(C) = %d, id(D) = %d' % (id(A), id(B), id(C), id(D)))
    A = 'bye'
    print(A,B,C,D)
    print('id(A) = %d, id(B) = %d, id(C) = %d, id(D) = %d' % (id(A), id(B), id(C), id(D)))

    查看打印结果:

    id(A) = 1992128, id(B) = 1992128, id(C) = 1992128, id(D) = 1992128
    bye hello hello hello
    id(A) = 1992256, id(B) = 1992128, id(C) = 1992128, id(D) = 1992128

    三、举例说明

    import copy
    
    
    def printid(x, name): #打印地址函数
        if isinstance(A, list):
            for i in range(len(x)):
                print(name + '[' + str(i) + '] =' + str(id(x[i])), end='  ')
        elif isinstance(x, dict):
            for key in x:
                print(name + '[' + str(key) + '] =' + str(id(x[key])), end='  ')
        print()
    
    A = ['a', 'b', ['c', 'd', 'e']]
    B = A
    C = copy.copy(A)
    D = copy.deepcopy(A)
    print('id(A) = %d, id(B) = %d, id(C) = %d, id(D) = %d' % (id(A),id(B), id(C), id(D)))
    printid(A, 'A')
    printid(B, 'B')
    printid(C, 'C')
    printid(D, 'D')
    printid(A[2], 'A[2]')
    printid(B[2], 'B[2]')
    printid(C[2], 'C[2]')
    printid(D[2], 'D[2]')
    A.append('f')
    A[0] = 'aa'
    A[2][1] = 'dd'
    A[2].append('hh')
    print('A = ', A)
    print('B = ', B)
    print('C = ', C)
    print('D = ', D)

    查看打印结果:

    id(A) = 41993400, id(B) = 41993400, id(C) = 41994160, id(D) = 41994120 
    A[0] =4790880  A[1] =4815712  A[2] =41993160  
    B[0] =4790880  B[1] =4815712  B[2] =41993160  
    C[0] =4790880  C[1] =4815712  C[2] =41993160  
    D[0] =4790880  D[1] =4815712  D[2] =41994080  #只有深拷贝中指向['c', 'd', 'e']的地址不一样
    #四个对象保存['c', 'd', 'e']中的每个原子对象的地址一样
    A[2][0] =4765856  A[2][1] =4766720  A[2][2] =4766656  
    B[2][0] =4765856  B[2][1] =4766720  B[2][2] =4766656  
    C[2][0] =4765856  C[2][1] =4766720  C[2][2] =4766656  
    D[2][0] =4765856  D[2][1] =4766720  D[2][2] =4766656  
    A =  ['aa', 'b', ['c', 'dd', 'e', 'hh'], 'f']
    B =  ['aa', 'b', ['c', 'dd', 'e', 'hh'], 'f'] #B = A
    C =  ['a', 'b', ['c', 'dd', 'e', 'hh']] 
    D =  ['a', 'b', ['c', 'd', 'e']]
    #A[0]保存字符串,是不可变的,所以A新开辟一个内存保存'aa',不影响B和C
    # id(C)和id(D)都与id(A)不相同,A中加入新的元素‘f’时,也不会影响B和C。id(A[2]) = id(C[2]),且A[2]保存的是一个容器对象,是可变的。因此A[2]变了,C[2]也会变
    #id(A[2])!=id(D[2]),且A[2][1]中保存的是字符串,是不可变对象。因此,A新开辟一个内存保存‘dd’,而D保持不变’‘’
  • 相关阅读:
    luogu P3174 毛毛虫
    P3386二分图最大匹配模版
    P4180 严格次小生成树
    差分约束
    高斯消元
    P1306 斐波那契公约数
    极值
    排序
    P1852 [国家集训队]跳跳棋
    高精度模版
  • 原文地址:https://www.cnblogs.com/jessicaxu/p/7726614.html
Copyright © 2020-2023  润新知