2013-05-03 55 views
2

如果我有這樣的Python代碼:創建Python的變量是相互獨立的

foo = [3, 5, 9] 
bar = foo 
bar.append(9) 
print(foo) 

它返回

[3, 5, 9, 9] 

這肯定意味着,當我追加9bar,它也影響foo 。如何使變量bar等於foo,但是這樣當我編輯bar時,它不會影響foo

回答

5

你正在改變一個可變的值,所以你需要一個明確的副本:

bar = list(foo) 

bar = foo[:] 

當分配給Python中的名字,你要做的就是存儲值爲。在不創建列表的副本的情況下,foobar都引用相同的列表。

對於非可變值,這不是問題;您將引用替換爲字符串,以指向不同的值。

但是列表(和dictset和大多數類的實例)是可變的。您沒有更改foo,您更改了foo指的是。你做了foo.append(9),Python認爲:

  • 查找值foo指的是。
  • 找到該值的屬性.append。這將在列表實例上返回一個方法。
  • 調用該方法,傳入值9。這改變了列表。

Python名稱本身只不過是標籤,指向實際值。您可以將值看作氣球,將名稱看作小紙標籤,分配是將標籤綁定到氣球的動作。 bar = foo創建了第二個紙標籤,該標籤與完全相同的氣球連接。

看到這個older answer of mine在哪裏我推動氣球比喻更多。

+0

+1,打我給它。我個人更喜歡使用'list()',因爲它可以與任何迭代器一起工作,我覺得它更具可讀性(它通過詢問[[:]'做什麼的問題來支持) 。 – 2013-05-03 15:36:24

+0

爲什麼這個Python代碼在ideone:http://ideone.com/QIjOsD沒有產生預期的結果(三個1,而不是四個)?我做錯了什麼? – LazySloth13 2013-05-03 15:51:45

+0

@Lewis:嵌套列表。您只複製* outer *列表。外部列表不過是一系列動態的紙質標籤,按順序編號。對於這些編號標籤,更多的字符串是更多的值,每個另外的列表。複製剛剛複製到標籤上的外部列表,包括將新字符串複製到任何它們綁定的內容。使用'copy'模塊創建一個深層拷貝('b = copy.deepcopy(a)'),或者使用列表理解:'b = [elem [:] for elem in a]'。列表理解爲每個包含列表創建一個淺表副本,用這些淺副本生成一個新的外部列表作爲元素。 – 2013-05-03 15:52:35

2

你讓一個副本:

bar = foo[:] #copy of foo 
bar.append(9) 

這與分配對象如何蟒蛇交易的事情。作業說「將對象放在右側,並將其存儲在本地名稱空間」「左側的名稱下。所以,就你而言,你有foo和bar引用同一個對象,這就是爲什麼追加到一個也會影響另一個。

使用運算符(通常爲)在適當的位置(例如+=)上對對象進行操作時,事物可以通過不可變對象變得更有趣。例如參見my answer here以及更多解釋。

1

使用deepcopy

>>> from copy import deepcopy 
>>> foo = [3, 5, 9] 
>>> bar = deepcopy(foo) 
>>> bar.append(9) 
>>> print(foo) 
[3, 5, 9] 
>>> print bar 
[3, 5, 9, 9]