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保持不变’‘’
原文地址:https://www.cnblogs.com/jessicaxu/p/7726614.html