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

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

+=运算符对于list来说会原地修改list的内容, 对于tuple来说则会重新创建一个对象并赋值给原引用变量。
为任意对象做浅复制和深复制
有些时候我们可能也需要深复制(即副本不共享内部对象的引用),我们可以使用copy模块提供的copy、deepcopy函数,他能为任意对象做浅复制和深复制。
函数参数作为引用时:
这种情况下函数形参为实参(引用类型)的副本,函数可能会修改作为参数传入的引用指向的对象,但不能将这个对象替换。
使用可变类型作为参数默认值引起的问题:

没有初始化的默认参数会指向同一个对象。
出现这个问题的根源是参数默认值会在函数对象定义时计算(通常在加载模块时),因此参数默认值成为了函数对象的属性,当这个默认值为可变类型时就容易出现我们意料之外的事情。
我们观察上述例子中t函数对象的__default__属性:

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


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