Python 浅拷贝、深拷贝详细图文解析

2020-03-03  本文已影响0人  时间煮菜

Python一大坑

今天在写算法题,到了01背包问题,我用了一个二维数组,在创建数组时,我用了这样的方法(自以为很简单,结果坑了一天)

In [69]: result = [[0] * 7] * 4

In [70]: result
Out[70]:
[[0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]]

我开始还很困惑,以为是我的算法有问题,还是太小白了,

后来才反应过来,可能是创建数组的时候发生了问题。

我进行了尝试,在修改值的时候,发现出现了这样的问题:

In [60]: result[0][1] = 3

In [61]: result
Out[61]:
[[0, 3, 0, 0, 0, 0, 0],
 [0, 3, 0, 0, 0, 0, 0],
 [0, 3, 0, 0, 0, 0, 0],
 [0, 3, 0, 0, 0, 0, 0]]

我只是给result[0][1]赋了值=3,怎么整个第二列都变成了3。

后经查阅资料,

list * n—>n shallow copies of list concatenated, n个list的浅拷贝的连接

In [64]:  lists = [[]] * 3

In [65]: lists
Out[65]: [[], [], []]

In [66]: lists[0].append(3)

In [67]: list
Out[67]: list

In [68]: lists
Out[68]: [[3], [3], [3]]

这里我就困惑了,到底什么是浅拷贝。

首先明确几点:

赋值

赋值并不会产生一个新的独立的对象,只是给原有的数据打上一个新标签。当其中的一个标签被改变时,这个数据就会发生变化,另一个标签也会随之改变。

先看一段代码:

In [141]: origin = [1, 2, 3] # [1, 2, 3]被贴上了标签origin

In [142]: eq = origin  # origin赋值给eq,[1, 2, 3]又被贴上了标签origin

In [143]: eq
Out[143]: [1, 2, 3]

In [144]: origin = [4, 5, 6]  # origin整体发生变化,相当于标签origin从[1,2,3]上撕了下来,贴给了[4, 5, 6]

In [145]: origin
Out[145]: [4, 5, 6]

In [146]: eq  # eq并没有发生变化,标签eq没有被撕下来
Out[146]: [1, 2, 3]
    
    

In [150]: origin = [1, 2, 3]

In [151]: eq = origin

In [152]: origin[0] = 4  # 只有origin[0]发生变化

In [153]: origin
Out[153]: [4, 2, 3]

In [154]: eq
Out[154]: [4, 2, 3]  # eq[0]也发生变化
In [155]: origin = [1, 2, 3]

In [156]: eq = origin

In [157]: origin == eq
Out[157]: True

In [158]: origin is eq
Out[158]: True

他们的值和引用相同。

参考文章python中copy()和deepcopy()详解

浅拷贝

先上代码:

In [1]: import copy

In [2]: origin = [1, 2, [3, 4]]  # 这里是不能是一维list,后面会详细说明

In [3]: cop1 = copy.copy(origin)

In [4]: cop2 = copy.deepcopy(origin)

In [5]: cop1 == cop2
Out[5]: True

In [6]: cop1 is cop2
Out[6]: False
#cop1 和 cop2 看上去相同,但已不再是同一个object

In [7]: origin[2][0] = "haha"  # 修改origin[2][0]

In [8]: origin
Out[8]: [1, 2, ['haha', 4]]

In [9]: cop1  # 浅拷贝的元素变了
Out[9]: [1, 2, ['haha', 4]]

In [10]: cop2  # 深拷贝的元素没变
Out[10]: [1, 2, [3, 4]]

以上我们分为进行了,shallow copy(浅拷贝)-> cop1

和deep copy(深拷贝)-> cop2

为什么浅拷贝的元素变了呢,如果有兴趣,你会发现在一维数组中,浅拷贝的元素也不会变

In [11]: origin = [1, 2, 3, 4]

In [12]: cop1 = copy.copy(origin)

In [13]: cop2 = copy.deepcopy(origin)

In [14]: origin[0] = "haha"

In [15]: origin
Out[15]: ['haha', 2, 3, 4]

In [16]: cop1
Out[16]: [1, 2, 3, 4]

In [17]: cop2
Out[17]: [1, 2, 3, 4]
image

深拷贝

image
上一篇 下一篇

猜你喜欢

热点阅读