初次接触深浅复制还是当年学习成c++时,我当时只是简单的记了一下结论,当时我是这样记忆的:简单的基本类型的对象是没有深浅复制的区分的,只有自定义的类,或者系统提供的类,用这些类实例化的对象的才存在深浅复制一说。至于这个深浅复制具体是什么,好像是与内存相关的,当时觉得没什么要紧的,就忽略之了。如今看来,这是大错特错的,任何一门图灵完全的编程语言都存在深浅复制这个重要的特性,今天再次学习这个深浅复制是学习 Python的一个库, copy 库。
这是一个专门用于拷贝各种数据类型的对象的库,其中有一个函数 deepcopy(), 与之对应的是 copy() 函数,显然前者是深拷贝,后者是浅拷贝。
就我目前的理解,如下代码:
a=1024
b=a
a=0
print("a=%d b=%d"%(a,b))
程序运行的结果是 a=0 b=1024
这就是我所记忆的基本类型没有深浅拷贝之分的结果,变量 a 保存着 1024 的内存地址,第二行意思就是把 a 保存的地址赋值于 b, 此时 b 也指向 1024 的内存地址, 第三行 a 重新指向 0, a 与 b 就是两条并行的线,互相之间没有任何关系了,初学者应该很容易理解,然而自定义类却是另外一种情况,先上代码
a=['a','b',1,2,3,4,5,6]
b=a
a.append('fang')
print(a)
print(b)
运行的结果却是 :
['a','b',1,2,3,4,5,6,'fang']
['a','b' ,1,2,3,4,5,6,'fang']
对,么有看错,我也没有写错,此时 a 与 b 是一样的值
照道理来说,此时 b 应该还是 a 改变值之前的值,然而事实并非如此, a 增加一个元素之后, b 也随着 a 增加, 所谓嫁鸡随鸡嫁狗随狗可能是描述浅复制的最通俗的表述吧!第三行 , a 增加一个元素,在内存中就多了一个元素,此时 a 的内存地址肯定是改变了的,但是 a 与 b 仍然指向同一个内存首地址,这里需要解释一下,python是动态类型语言,在此处的具体表现为 list 内的元素类型可以完全不同, append() 的时候,在内存中,只是把一个新的内存首地址连接到list的末地址中,这样就组成一个新的列表,而由于 b 也是指向这个列表的首地址,因此打印 b 也是与 a 相同的一个值。
但是实际编程过程中,我们拷贝了一个对象,就是希望这个拷贝与原来这个对象分道扬镳,么有任何关系,那么怎么解决呢?
这就呀要使用到 copy 中的deepcopy函数了
如下代码:
import copy
a=['a','b',1,2,3,4]
b=copy.deepcopy(a)
a=['kok']
print(a)
print(b)
此时运行的结果就是
['kok']
['a','b',1,2,3,4]
也就是这个拷贝与原来的对象彻底脱离了关系