2015-04-03 56 views
2

如果您有列出的以下列表:在Python分配中列出的清單列表到另一個列表

>> A = [[1], [2]] 

然後說你的第二個列表分配給第一個列表:

>> A[0] = A[1] 

你結束了以下內容:

>> print A 
[[2], [2]] 

所以A [0]和A [1]指向同一個列表了。如果通過追加元素到第一種:

>> A[0].append(3) 

您將獲得以下:

>> print A 
[[2,3], [2,3]] 

但是,如果您嘗試通過刪除第一個列表:

>> del A[0] 

然後只刪除一個列表,如下所示:

>> print A 
[[1,2]] 

Q1.1:爲什麼行爲不同?有人可能會期望這兩個列表被刪除。

顯然,如果一個只想做一個的副本[1],則以下工作正常:

>> A = [[1], [2]] 
>> A[0] = list(A[1]) 
>> print A 
[[2], [2]] 
>> A[0].append(3) 
>> print A 
[[2,3], [2]] 

這樣做的問題是,它的運行時間與列表的大小線性複製,即A [1]。

Q1.2:在沒有線性時間複製操作的情況下,是否可以從另一個複製列表?

回答

1

Q1.1

您必須區分對象和對象標識。身份只是對象的存儲單元的邏輯地址。當你在做A[0] = A[1]時,你實際上並不複製對象,但是你得到了對象的新身份。 A[0] = A[1]之後,你有兩個身份A[0]A[1]到同一個對象,所以當你做A[0].append(...)A[1].append(.),實際上受到影響的是同一個對象。

現在關於列表。 Python中的列表不包含對象。他們持有對象的身份。您可以通過比較

sys.getsizeof([1])sys.getsizeof([1000000000000000000000000000000])

都將具有相同的尺寸雖然10000000000000000000000000000000明顯重於1檢查。

不會有什麼del,它從列表中刪除,這恰好是兩個身份而不是對象之一,一個元素,所以當你有擁有兩個身份相同的對象和del一個列表其中,您仍然保留對象和其他標識,因爲該對象仍被引用爲

Q1.2

如果你想複製,你可以做A[0] = A[1][:],它將A[0]分配到一個切片。它應該更快。檢查this

+0

我會說「引用」而不是「身份」;我認爲「參考」是更常用的術語? – Vultaire 2015-04-03 06:42:20

+0

@Vultaire它可能只是在python的[documentation](https://docs.python.org/3.4/reference/datamodel.html)中使用的「identity」,所以我只是使用「identity」來保持它的一致性。 – khajvah 2015-04-03 06:43:56

+0

從@ itzmeontv的回答中,您可以通過id(A [0])來獲取身份值。 – TrainedScarab 2015-04-03 06:49:47

0

del A [0] 並不意味着要刪除A [0]元素的條目並且將在垃圾回收時被刪除。它僅代表刪除從A [0]變量到列表([2,3])的引用鏈接。

0

Q1.1:爲什麼行爲不同?人們可能會期望這兩個清單被刪除。

del A[0] 

不重新分配的list[2,3]或存儲器,也不刪除list。它只是移除標籤或referevce A[0]到列表[2,3]

Q1.2:在沒有線性時間複製操作的情況下,是否可以從另一個複製列表?

A[0] = A[1][:] 

例如

A = [[1], [2]] 
A[0] = A[1][:] 

>>id(A[0]),id(A[1]) 
(140215217604552, 140215217619208)