天天看點

python嵌套List建立的坑

先來看一段代碼,

>>> dp = [[[0] * 2] * 3 for _ in range(4)]
>>> dp
out: [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]
>>> id(dp[0][1])
out: 140101203415920
>>> id(dp[0][0])
out: 140101203415920
>>> dp[0][1][1] = -3
>>> dp
out: [[[0, -3], [0, -3], [0, -3]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]      

好玩嗎? dp[0][0], dp[0][1], dp[0][2]竟然是同一塊記憶體空間,對一個索引指派,竟然全部的索引都被修改了。

我們來探究一下原因,看下面這樣的代碼。

>>> a = [0] * 2
>>> id(a[0]) == id(a[1])
out: True
>>> a[0]=1
>>> id(a[0]) == id(a[1])
out: False      

當我們使用list的乘操作建立一個清單的時候,裡面的每個元素的位址都是一樣的,​

​清單的乘操作就是重複引用,每個被乘的元素都會引用同一塊記憶體位址​

​,是以第二個例子中的 0 和第一個例子中的 [0, 0] 都會使用同一塊記憶體空間。

那為啥第一個例子中對一個索引修改值,其他索引跟着變,而第二個例子中沒有呢,其中一個索引更換一個值,他的記憶體位址也變了?

這是因為在python中每個數字都有不同的記憶體位址,但是一個list不具有這種屬性,他們還是指向同一個記憶體位址。

dp = [[[0]*2 for _ in range(3)] for _ in range(4)]