在过往的面试中,面试最频繁的题目之一就要属赋值、深拷贝与浅拷贝这个问题的原理了,明天就来带大家解析这个问题。
首先,这个问题设计的知识点是什么?大家必须先搞清楚这个问题。这个问题波及到了咱们计算机的底层 —- 内存。那么咱们当初怎么来解析这个问题呢?这个问题问咱们的是赋值、深拷贝和浅拷贝在咱们的内存当中到底是一个什么样的体现模式。
大家都晓得,万物皆对象,对象就是内存调配的一块存储区域,那么这个问题的艰深说法就是,赋值有没有在内存当中划分区域,深拷贝和浅拷贝划分区域有什么区别?咱们一个个来讲
赋值
赋值即给值赋予一个变量(名称),使得咱们能够应用到这个值。
在内存中存在几种 id 固定不变的数据:int 类型、字母、空格等
对于 id 不定不变的数据,若同时赋值给两个变量,那么两个变量就是同一个对象,都会指向这个值所在的内存地址。
a = 123
b = 123
print(id(a), id(b))
执行后果:(1590328144, 1590328144)
那么其余的数据类型(比方字符串,列表,字典等),如果同时赋值给两个变量,那么他们就是两个对象,别离指向各自数据的内存地址。
a = [1, 2, 3]
b = [1, 2, 3]
print(id(a), id(b))
执行后果:1881566679560 1881566679240
如果不给 b 赋值,间接令 b = a, 那么他们就是一个援用的关系,b 援用 a 的对象,会指向 a 所在的内存地址。(咱们在面试过程中被问到赋值,通常面试官也是指这个景象,答复这个即可)
a = [1, 2, 3]
b = a
print(id(a), id(b))
执行后果:2166563410440 2166563410440
浅拷贝
这里咱们会用到一个库 copy(python 自带的)。浅拷贝的意思就是当一个数据有数据类型嵌套的状况存在时(例如 [1,2,[3,4,5]]), 只能将里面那层数据拷贝进去成为一个齐全独立的个体,也就是说生成一个新的对象,而第二层数据无奈拷贝进去,只是援用过去而已,内存地址不变,这就会造成一个景象:批改其中一个对象的外层数据,另一个对象的数据不会发生变化,而批改其中一个对象的内层数据,另外一个对象的数据也会发生变化。
import copy
a = [1, 2, 3, [4, 5, 6]]
# 浅拷贝
b = copy.copy(a)
# 批改第一层数据
a[0] = 10
print(a)
print(b)
print(id(a), id(b))
执行后果:[10, 2, 3, [4, 5, 6]]
[1, 2, 3, [4, 5, 6]]
1724296570184 1724296571464
import copy
a = [1, 2, 3, [4, 5, 6]]
# 浅拷贝
b = copy.copy(a)
# 批改第二层数据
a[3][0] = 10
print(a)
print(b)
print(id(a), id(b))
执行后果:[1, 2, 3, [10, 5, 6]]
[1, 2, 3, [10, 5, 6]]
1813604181320 1813604182600
深拷贝
深拷贝和浅拷贝的区别就是,不论数据类型中嵌套了多少个数据类型,它会把所有的数据都齐全拷贝进去成为一个全新的对象,批改其中任何一个数据都不会影响另外一个对象的数据。
import copy
a = [1, 2, 3, [4, 5, 6]]
# 深拷贝
b = copy.deepcopy(a)
# 批改第二层数据
a[3][0] = 10
print(a)
print(b)
print(id(a), id(b))
执行后果:[1, 2, 3, [10, 5, 6]]
[1, 2, 3, [4, 5, 6]]
2274488001864 2274488003144
结语
那么看到这儿,大家对咱们这个赋值、浅拷贝和深拷贝明确了吗?赋值就是将对象的数据间接拿过去用,并不会扭转内存地址。浅拷贝会讲对象数据的第一层拷贝进去成为一个新的对象,所以地址扭转了,然而第二层乃至更深层的数据只会援用过去,并不会生成一个新的地址,所以扭转它外面的数据两个对象的数据都会发生变化。深拷贝则会把所有的数据全副拷贝成为一个新的对象,地址齐全扭转,所以扭转其中一个对象的数据,另一个对象不受影响。
当前大家遇上了这个问题,以这样的形式去答复,相对是满分。