一、引用、浅拷贝、深拷贝
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保持不变’‘’