2014-10-05 21 views
0

我想我已經解決了我自己的問題,但我正在尋求更好的理解爲什麼,或者開明/設置直。填充列表 - 什麼是python在做什麼?

我有一個列表我打電話VEC:

vec = [0.0, 0.0] 

數據在讀取其中的變化值

,以比較當前和以前的值,我還有一個名單,我稱之爲oldvec 。 如果我定義爲oldvec

oldvec = vec 

那麼每次VEC的變化值的變化值,所以比較是沒有用的 - 他們總是相同的。

不過,如果我不是寫

oldvec = [vv for vv in vec] 

我沒有這個問題 - oldvec保持其價值甚至VEC的變化,所以當前和先前向量之間的比較可以作爲我需要它,即它實際上檢測重複和不重複! ...爲什麼?

+1

只需添加到下面的所有很好的答案,你可能會喜歡閱讀的會員斯內德爾德與可愛的圖,[關於Python的名稱和值事實與神話]全面的文章(http://nedbatchelder.com /text/names.html)。 – 2014-10-05 05:43:47

+0

[Python引用]的可能重複(http://stackoverflow.com/questions/2797114/python-references) – simonzack 2014-10-05 06:46:19

+0

哇,太棒了!非常感謝所有優秀的信息(包括鏈接)。 – user3903270 2014-10-05 06:52:59

回答

1

你可以看到底下發生了什麼的一種方法是使用id函數。這顯示了一個對象的內存地址。內存地址指的是對象存儲在物理內存中的位置。

如果我們運行這三個命令,並在不同的地址看(這只是我的電腦上;如果你自己運行它,你會得到不同的號碼):

>>> vec = [0.0, 0.0] 
>>> print id(vec) 
4501729936 

>>> oldvec1 = vec 
>>> print id(oldvec1) 
4501729936 

>>> oldvec2 = [vv for vv in vec] 
>>> print id(oldvec2) 
4502046984 

我們看到, vecoldvec1指的是相同的地址,所以它們是同一個對象的兩個不同的標籤。在引擎蓋下,Python正在操作地址爲4501729936的對象:變量名稱vecoldvec1只是我們使用的方便標籤。他們不提到「不同的」對象。

相比之下,oldvec2是完全不同的地方。當Python運行列表理解時,它不知道這會產生與以前相同的列表,因此它會創建該列表的新副本。


下面是一張快速的骯髒圖片來展示正在發生的事情。儘管紅色blob和綠色博客碰巧包含相同的信息,但它們是兩個不同的blob。 vecoldvec1指向相同的紅色斑點,因此任何一個操作都會影響底層的紅色斑點,並反映在另一個紅色斑點中。相比之下,oldvec2指向一個完全不同的綠色斑點,它恰好是紅色斑點中的信息的副本,但對綠色斑點的更改不會影響紅色斑點。

enter image description here

0

在Python中,變量是「引用」,這意味着您可以有兩個變量引用同一個對象。在你的第一個例子中,發生了什麼:同一個列表中有兩個名字。

如果您需要第二個實際列表,您可以「複製」第一個。有關如何,請參閱此處:How to clone or copy a list?

請注意,這也適用於列表中的項目 - 如果它們是更復雜的對象,則可以選擇對列表執行「深層複製」,將每一個每個元素的一部分,或者一個「淺拷貝」,只複製引用,所以你會有一個新的列表包含對原始對象的新引用。您需要爲每個用例選擇正確的方法。

1

將oldvec設置爲vec可以使oldvec指向vec。你還沒有創建一個新的列表,你只是爲它創建了另一個名字。通過使用列表理解,您可以顯式創建列表的新副本,等同於vec.copy()。

0

您應該將Python列表視爲一個對象:在內存中的某處實例化某個對象,並使用一個或多個指針存儲其內存地址 - 即當您說[]時,您正在內存中某處分配一些新空間。所以,當你撥打vec = [0.0, 0.0]時,它會在內存中的某個地方創建一個新列表,而它的地址爲存儲在vec變量中。所以,當你做oldvec = vec時,你只需將地址從vec複製到oldvec即可。

讓我用一個例子來說明:例如,想象一下,您的列表[0.0, 0.0]存儲在地址0x0800。當你說vec = [0.0, 0.0],vec變量現在收到0x0800。當你說oldvec = vecoldvec收到相同的0x0800。因此,當您訪問oldvec的第一個元素時,確實正在訪問指向vec指向的相同的列表。

現在,想想你的新行:oldvec = [vv for vv in vec]。當你做[],它創建一個新的列表,在內存中的其他地方,對吧?該列表中填充了vec的元素,如for命令所述。因此,它會在內存中的其他位置創建一個新列表,存儲0.00.0(如果我正確理解了您所解釋的內容,則稍後再添加新元素)。這就是Python內部處理命令的方式。

希望有所幫助。

相關問題