2011-07-22 88 views
17

當我運行此腳本(Python的V2.6):變量賦值和修改(在python)

a = [1,2] 
b = a 
a.append(3) 
print a 
>>>> [1,2,3] 
print b 
>>>> [1,2,3] 

我預計print b輸出[1,2]。當我所做的一切都改變了,爲什麼b變了?是否永久綁定了一個?如果是這樣,我可以讓他們獨立嗎?怎麼樣?

+1

可能重複[如何克隆Python的list?(http://stackoverflow.com/questions/2612802/how-to-clone-a-list-in-python ) –

+3

@Felix我會說不太重要 - 他不是隻問如何克隆,而是爲什麼Python會以某種方式行事。 – thegrinner

+3

「[Python has names](http://python.net/~goodger/projects/pycon/2007/idiomatic/presentation.html#python-has-names)」是關於這個更好的教程/介紹的很好的一部分行爲。 – nagisa

回答

36

內存管理涉及到包括所有的Python對象和數據結構私有堆內存位置。

Python的運行時間只有在對對象的引用(這都住在堆)交易:發生的事情Python的堆棧總是引用住在別處的值。

>>> a = [1, 2] 

python variables

>>> b = a 

python variables

>>> a.append(3) 

python variables

在這裏,我們可以清楚地看到,可變b被綁定到相同的對象a

可以使用is運營商的測試,如果兩個物體在物理上是相同的,這意味着如果他們有在內存中的同一地址。這也可以使用id()函數進行測試。

>>> a is b 
>>> True 
>>> id(a) == id(b) 
>>> True 

所以,在這種情況下,必須明確要求拷貝。 一旦你完成了,兩個不同的列表對象之間將不再有連接。

>>> b = list(a) 
>>> a is b 
>>> False 

python variables

4

簡答題 - 指針。

當您鍵入b = a時,它將b設置爲查看與a相同的陣列。你必須用元素的副本來創建一個新數組來分離它們。在這種情況下,像b = [n for n in a]這樣的東西可以正常工作。對於更復雜的操作,您可能需要檢出http://docs.python.org/library/copy.html

+2

也'B = A [:]'作品,它更 「Python化」(或所以他們說) –

12

Python中的對象通過引用存儲 - 您不將a的值分配給b,而是指向指向a指向的對象的指針。

通過值效仿分配,你可以複製像這樣:

import copy 

b = copy.copy(a) 

# now the code works as "expected" 

意識到這個具有性能缺點。

在陣的情況下,有依賴於切片的特殊方法:

b = a[:] 

# code also works as expected here 

更新 - 除此之外,一些對象,你可以使用構造,這包括清單:

b = list(a) 
+2

DiggyF在下方留言,指出了這一點 - 你要更換'B = A [:]'和' b =列表(a)'出於可讀性原因以及與numpy一起工作的任何內容。 – thegrinner

3

a是一個指針列表[1,2]

當您完成賦值b = a時,b的值是列表[1,2]的地址。

所以當你做a.append(3)你實際上並沒有改變a,你正在改變a指向的列表。由於ab都指向相同的列表,因此它們在修改其他列表時都會發生更改。

4

你可能想看看this鏈接。您在這裏遇到的問題是ab都指向相同的內存位置,因此更改一個會更改另一個。相反,你想要做這樣的事情:

a = [1,2] 
b = list(a) 
+3

來自鏈接中的文章:「下次你看到一個[:]嘗試用列表替換它時,你的代碼應該更具可讀性,做到這一點,魔鬼就在細節中。」所以建議使用'b = list(a)'。這也是一個好主意,因爲當人們從一個列表切換到一個numpy數組時,那麼一個[:]將被引用相同的數據。 – SiggyF

+0

@DiggyF好點。固定。 – thegrinner

2

如果你只是想列表中的內容複製到B,而不是使BA指針:

b = a[:] 

使用分割運算將列表中的內容複製到b中,這樣你的例子就是成爲:在Python

a = [1,2] 
b = a[:] 
a.append(3) 
print a 
>>>> [1,2,3] 
print b 
>>>> [1,2]