直接赋值:其实就是对象的引用(别名)
浅拷贝(copy):拷贝父对象,不会拷贝对象的内部子对象。
深拷贝(deepcopy): copy模块的deepcopy方法,递归完全拷贝了父对象及其子对象。(对于不可变类型做了优化,使其指向同一个地址,因为不可变类型的值发生变化,计算机会重新分配地址空间)
关于直接赋值、不可变类型和可变类型的面试题
运行以下代码会发生什么变化?为什么?
1 a = [1, 2, 3] 2 b = a 3 c = b 4 a = a + [4, 5, 6] 5 b += [7, 8, 9] 6 print(a) 7 print(b) 8 print(c) 9 #[1,2,3,4,5,6] 10 #[1,2,3,7,8,9] 11 #[1,2,3,7,8,9]
解答说明:
a的值赋值给b,b的值赋值给c, a,b,c指向同一个地址空间,其id值一致 当执行a = a + [4,5,6]时,计算机拿到a地址里面的内容与[4,5,6]做运算的结果为[1,2,3,4,5,6]。计算机分配一个新的地址存储结果,并把结果的名称设置为a。此时打印id(a)时会发现id发生变化 当执行b += [7, 8, 9]时本质上是在执行列表变量的 extend 方法,不会修改变量的引用 。因此id(b), id(c)的值没有发生变化。
关于深浅copy的面试题
运行以下代码会发生什么变化?为什么?
1 from copy import copy, deepcopy 2 3 a = {'a': 'c', 'b': ['d']} 4 b = copy(a) 5 c = deepcopy(a) 6 a['e'] = 'f' 7 a['b'].append('g') 8 print(a) 9 print(b) 10 print(c) 11 #{'a': 'c', 'b': ['d', 'g'], 'e': 'f'} 12 #{'a': 'c', 'b': ['d', 'g']} 13 #{'a': 'c', 'b': ['d']}
解答说明:
b是浅copy:拷贝父对象,不会拷贝对象的内部子对象,b的id发生变化,而内部对象的地址没有发生变化,当一些可变类型发生变化,和其指向同一个地址的变量也会发生变化 c是深copy,拷贝父对象, 深拷贝是对于一个对象所有层次的拷贝,对于可变类型的对象会完全拷贝一个到一个新的地址空间。
1 from copy import copy, deepcopy 2 3 a = {'a': 'c', 'b': ['d']} 4 print(id(a), end=' ') 5 for i in a.values(): 6 print(i, id(i), end=' ') 7 print(' ') 8 9 b = copy(a) 10 print(id(b), end=' ') 11 for i in b.values(): 12 print(i, id(i), end=' ') 13 print(' ') 14 15 c = deepcopy(a) 16 print(id(c), end=' ') 17 for i in c.values(): 18 print(i, id(i), end=' ') 19 print(' ') 20 a['e'] = 'f' 21 22 a['b'].append('g') 23 print(a) 24 print(b) 25 print(c)