赋值,浅复制,深复制的区别
赋值
首先是赋值:赋值并不会产生一个独立的对象单独存在,可以看作是给某对象贴上一个新标签
看下下面这段代码
1 | a = [1, 2, 3, 4, 5] |
运行结果是
1 | [1, 2, 3, 4, 5] |
可以看到令b = a后,给a重新赋值,b并没有改变
再看下面这段代码
1 | a = [1, 2, 3, 4, 5] |
运行结果是
1 | [2, 2, 3, 4, 5] |
这里可以看到改变a[0]的值后,b[0]也发生了改变
怎么理解这个呢,得先了解python的数据存储方式
python的数据存储方式
python的数据存储方式与其他OOP语言不同。它与其说是把某个值赋给变量,不如说是给变量建立了一个到具体值的引用
以上面的两段代码为例,先看第一段代码
a = [1, 2, 3, 4, 5],这个语句可以看成是将a这个标签贴到了[1,2,3,4,5]这个列表上,然后b = a,可以看作又将b这个标签贴到了[1,2,3,4,5]这个列表上,之后a = [2,3,4,5,6],便是将a这个标签从[1,2,3,4,5]这个列表上拿下来,贴到了一个新列表上,所以实际上b指向的列表并未发生变化
再看第二段代码
同样是将a,b这两个标签先后贴到[1,2,3,4,5]这个列表上,然后a[0] = 2,这个语句是真正改变了[1,2,3,4,5]这个列表中的元素,而b这个标签是指向该列表的,于是相应的b[0]也发生了改变
深复制
直接给出结论,深复制是产生一个独立于原对象的新对象,新对象与原对象之间不会互相影响
可以看下面这个列子
1 | import copy |
运行结果是
1 | [1, 2, 3, 4, 5] |
浅复制
浅复制要分两种情况进行讨论:
当浅复制的对象是不可变对象(数值,字符串,元组)时和“等于赋值”的情况一样,对象的id值与浅复制原来的对象相同
当浅复制的对象是可变对象(列表,集合和字典)时,又分为两种情况:
第一种情况: 浅复制的对象中无复杂子对象时,新对象与浅复制原来的对象不会互相影响,id值不同
第二种情况: 浅复制的对象中有复杂子对象时,如果不改变其中复杂子对象,浅复制的值改变并不会影响原对象的值。但是改变其中的复杂子对象,则浅复制的值改变会影响原对象的值
看下面两个例子
1 | import copy |
结果是
1 | [[1, 2, 3], 2, 3, 4, 5] |
可以看到改变b[1]并没有影响a的值,再看第二个例子
1 | import copy |
可以看到改变b[0] [0]的值影响了a的值