大家好!拷贝在我们的代码开发中是经常使用的,但是在招聘面试的时候会发现,可能这个面试者已经工作多年,当被提问:"请讲一下在python中浅拷贝和深拷贝有什么不同? 详细讲一下它们的应用",很多面试者也是简单几句,傻傻分不清,今天我们就浅拷贝和深拷贝做一下讲解。
想要搞明白这个问题,首先我们需要搞清楚,python中的 变量、引用、对象以及什么是可变对象、什么是不可变对象?
变量:可以理解为一个元素,具有指向对象的连接空间,也可以理解为是对象的引用;
对象:可以理解为有分配的一块内存空间,用来存储其代表的值;
引用:可以理解为是一个从变量到对象的指针;
可变对象:在python中可以改变的对象,可以添加、删除、修改对象内部元素的,比如像 列表、字典等;
不可变对象:在python中对象一旦创建,不可再对其内部元素进行修改的对象,比如像 元组、字符串;
了解了以上的概念,我们来先看一下赋值:
运行结果:
从以上结果我们可以看到:
当被复制的变量a*所指向的是可变对象时,赋值变量b,d会因为a*所指向的对象改变而改变;是因为b、d与a*所指向的对象地址是一样的,对象地址发生改变,但是指向并未发生改变。
当被复制的变量a2所指向的是不可变可变对象时,赋值变量c会不会因为a2所指向的对象改变而改变;是因为a2的地址引用的对象发生了改变,重新分配了一个内存是一个新的对象,所以c不会发生改变。
由此我们得出结论:直接赋值其实就是对象的引用。
当初始对象变量所指向的是可变对象,但是赋值新的变量想要保持不受初始变量的影响的话,我们通常会使用以下两种方法,也是我们要讲的深拷贝和浅拷贝:
第一种方法:该方法只针对可切片的序列可用,比如列表;可以整体切割,算是浅拷贝,只拷贝第一层级对象。
执行方法:下图可以看到新的变量已不受源变量的影响了。
第二种方法:使用python中的copy模块包
copy.copy(x):浅拷贝,只拷贝父级第一层级的对象,或者顶级对象;
copy.deepcopy(x):深拷贝,每个层级的对象都会被拷贝,无论是单层还是多个层级。
执行结果:
当然我们也可以打出对象的内存地址观察其变化,不可变对象因初始值改变只能是变量重新引用新的地址,深拷贝和浅拷贝的结果肯定不受其影响。
结论:
单层级中,无论是可变对象还是不可变对象,初始对象改变后,浅拷贝和深拷贝的结果都不受影响;
多层级中,初始对象改变后,不可变对象浅拷贝和深拷贝的结果都不受影响,可变对象浅拷贝会随着内部层级的改变而发生改变,深拷贝不受影响。
今天的讲解就到这里,希望对大家有所帮助,欢迎关注、点赞收藏,谢谢~