查看原文
其他

面试必备之Python深、浅拷贝。

爱德宝器 数据管道 2022-12-12

聊Python的浅拷贝深拷贝问题之前,先举一个例子:现在你有一份家族名字的列表,你家里人想让你们加入Ed家族但是要保证之前的家族名字列表保持不变,你可能会写一个Python程序如下如:

你发现你确实使得家族名字前面都加上了“Ed”,但与此同时你把原始的家族名字列表也给修改了,这是什么问题导致的呢?下面请看。

变量、引用、对象

开场白:在Python中,有一句话:“一切皆为对象,一切皆为对象的引用“,所以 只要记住这句话就很容易清楚python中的引用、浅拷贝和深拷贝了

在Python中使用一个变量时,都没有声明变量的存在和类型,但变量还是可以工作,如输入a = 1,Python为什么知道那代表一个整数呢?这是因为在Python语言中,这些都是以一个非常自然的方式完成,就像下面这样:

  • 变量创建:一个变量名,就像a,当代码第一次给它赋值时创建了它。

  • 变量类型:类型的概念是存在于对象中而不是变量名中,这里也就是代表上面的1。

  • 变量使用:当变量出现在表达式中,它马上会被当前引用的对象所代替,无论这个变量是什么类型。此外,所有变量必须在使用前明确赋值,使用未赋值的变量会发生错误。

总而言之,变量在赋值的时候才创建,它可以引用任何类型的对象,并且必须在引用之前赋值,所以a = 1实际在Python中有三个操作:

  1.     创建一个对象代表值1

  2.     创建一个变量a

  3.     将变量与对象1连接

重点:类型属于对象,而不是变量,a = 1意思说的不是a就是整型,而是1是整形,只是创建好对象1以后,a被引用的对象1代替。

直接复制

直接赋值举例:

可以看出赋值的时候修改b的列表,a的列表跟着一起修改,并且a,b引用的对象地址相同。(id方法的返回值就是对象的内存地址

原因

b = a赋值引用,a和b都指向同一个对象。

解析图:

注:上图解析图来之“易佰教程”

浅拷贝

浅拷贝举例:

现在a,b是一个分别指向独立的对象,所以他们的内在地址不一样,但修改b里面的列表,a也会变。

原因

b = a.copy(): 浅拷贝, a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象(是引用)。

解析图:

注:上图解析图来之“易佰教程”

深拷贝

深拷贝举例:

可以看出a,b的内存地址不一样,并且修改b内部的值,a里面的值不会变。

原因

 a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。

解析图:

注:上图解析图来之“易佰教程”

总结

现在已经知道了深、浅拷贝的意思,可以修改第一个程序保证家族名字加一个“Ed”并且保持原始的家族列表不变,具体如下:

  • 列表切片保持副本的方法(实际是浅拷贝)

  • 利用深拷贝

更多关于对象、变量引用的关系请阅读《Python学习手册》(Learning python)第6章“动态类型简介”。(强烈推荐阅读,对理解Python程序非常有帮助)

关注“数据管道”,回复“python学习手册”即可获得第四版中文版和第五版英文版书籍。另qq群也会上传。

题外话之电影推荐:《这个男人来之地球》

“我可以给你一句十个字的十诫:别别别别别别别别别别”

“I can give you the ten commandments in ten words:Don't,Don't,Don't,Don't,Don't,Don't,Don't,Don't,Don't,Don't


长按下方二维码关注我们

不断升华自己的过程中

你我一起进步


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存