直接赋值
首先创建一个列表 a , 然后将 a 赋于 b ,此时 a 和 b 均为 [ 11,22 ]
此时 b 存在两种可能,可能 b 直接 复制了一份 a 开辟了一个新的内存空间,或者 b 指向 a 所对应的值
在C语言中,是直接开辟新的内存空间,而在python中,b 指向 a 所对应的值
验证如下, a 添加 一个元素 ,查看 b 的值是否改变,结果如下(左边是C语言,右边是python)
id函数可以查看参数变量对应的内存地址,即判断a b 是否真正是同一个值
浅拷贝和深拷贝
使用 copy 模块的深拷贝方法 deepcopy() 拷贝 a 给 c ,此时 a c 地址不一样,说明 深拷贝 直接开辟新空间复制了一份出来
定义 c 为 【a,b】 将 c 再赋给 d ,此时均为 直接赋值,所以原理如图所示
继续使用 copy 模块的浅拷贝方法 copy()拷贝 c 给 e
此时,使用浅拷贝会出现两种情况,可能 e 直接 复制了一份 c 开辟了一个新的内存空间,或者 e 指向 c 所对应的值
验证如下,id(c)和 id(e) 的值不一样,说明开辟了新的空间,拷贝了一份 c
此时,又有两种情况
e 中 指向 a 和 b 所对应的值
e 直接 拷贝 a 和 b 的值,存储在 e 中
验证,打印 c[0] 地址,和 e[0] 如果是第一种情况,地址相同,第二种情况,地址不同
如图,地址相同,是第一种情况,还是引用指向,添加 a 元素 再次验证,e 和 c 均改变
总结,浅拷贝 copy() 方法特征,只拷贝最外层,开辟新空间,里面不变,如果里面是引用指向,并不继续拷贝,照旧
对应的,深拷贝 deepcopy()方法特征,拷贝所有,如果里面是引用指向,也拷贝,验证如下
首先,d 拷贝了c 开辟了新的空间,id(c) id(d) 不同,id(c[0]) 和 id(e[0]) 不同,说明 e 直接 拷贝 a 和 b 的值,存储在 e 中
再次验证,添加 a 的元素 c 改变,而 e 还是原来的值,没有变
补充:
创建一个元组时,
进行浅拷贝,此时,id(a) 和 id(b) 相同,说明并没有按照正常拷贝,开辟新的空间,仅仅是增加指向,类似直接赋值过程
原理也很好理解,元组创建后不可修改,意义不大
深拷贝同理也是
如果元组内有可变元素,进行浅拷贝时,是指向,进行深拷贝时,开辟新空间进行拷贝
列表切片时是 浅拷贝
字典中的 COPY 方法拷贝一个字典,字典无序,字典中 key是在字典中存放, value只是指向,并不在字典中存放
验证时,添加一个 key:value value为一个列表,修改 value,打印 d 和 co 发现都改变,说明字典copy中value共享
是浅拷贝
调用函数 C语言中,不会修改实参的值,Python中 参数调用浅拷贝时,会改变,深拷贝时,并不会改变
使用 浅拷贝 or 深拷贝 取决于具体情况而定