3 默认做浅复制

在Python中复制list或其他可变集合时,使用的类型构造方法或切片默认的都是浅复制,也就是说对于对象中的对象只是复制了一个地址,如下。

3 默认做浅复制_第1张图片

如果在容器中有可变对象的引用可能会造成无法预期的结果。


3 默认做浅复制_第2张图片

+=运算符对于list来说会原地修改list的内容, 对于tuple来说则会重新创建一个对象并赋值给原引用变量。


为任意对象做浅复制和深复制

有些时候我们可能也需要深复制(即副本不共享内部对象的引用),我们可以使用copy模块提供的copy、deepcopy函数,他能为任意对象做浅复制和深复制。

函数参数作为引用时:

这种情况下函数形参为实参(引用类型)的副本,函数可能会修改作为参数传入的引用指向的对象,但不能将这个对象替换。

使用可变类型作为参数默认值引起的问题:

3 默认做浅复制_第3张图片

没有初始化的默认参数会指向同一个对象。

出现这个问题的根源是参数默认值会在函数对象定义时计算(通常在加载模块时),因此参数默认值成为了函数对象的属性,当这个默认值为可变类型时就容易出现我们意料之外的事情。

我们观察上述例子中t函数对象的__default__属性:

我们每次调用t这个函数对象时,其实是共享了这个函数对象的默认值,对于值为可变类型的参数来说每次调用实际上操作的是同一个对象,对于上述例子来说每次调用时l默认都只是t函数对象__defaults__属性(包含有个或多个默认值)中某一个元素的别名而已。

具体请看下面的例子:

3 默认做浅复制_第4张图片
3 默认做浅复制_第5张图片

这也是我们为什么会将函数参数的默认值设置为None。

你可能感兴趣的:(3 默认做浅复制)