2012-03-15 46 views
5

我對Python引用感到困惑。請看下面的例子:Python的引用是如何工作的?

我的任務:要在列表

d = { 'm': [1,2,3] } 
m = d['m'] 
m = m[1:] # m changes its reference to the new sliced list, edits m but not d (I wanted to change d) 

同樣編輯每一個元素:

d = { 'm': [1,2,3] } 
m = d['m'] 
m = m[0] # As per python referencing, m should be pointing to d['m'] and should have edited d 

在Python中一切順利的通過引用,那麼當一個新對象產生的? 我們總是需要copydeepcopycopy模塊來製作對象副本嗎?

請說明。

+1

如果你是一個視覺學習者,[這裏](http://people.csail.mit.edu/pgbovine/python /)一個很好的教程 – forivall 2012-03-16 00:19:33

+0

非常有用的評論@jordoex先生 - 真的很棒! – 2012-03-16 05:18:25

回答

11

在Python中,變量不是一個容納東西的盒子,它是一個指向對象的名稱。在您的代碼:

  • d = { 'm': [1,2,3] } - >綁定名稱d到詞典
  • m = d['m'] - >綁定名稱m到列表
  • m = m[1:] - >綁定名稱m到另一個列表

您的第三行不會改變m本身,但是m指向的是什麼。

要編輯列表中的元素是你可以做的是:

m = d['m'] 
for i, item in enumerate(m): 
    result = do_something_with(item) 
    m[i] = result 
+0

除了'enumerate'之外,還有別的方法可以編輯這個列表的每個元素嗎? – 2012-03-15 17:47:15

+0

「指向對象的名稱」可能會令人困惑,因爲「指針」不是Python術語。我只是說「這是一個對象的名稱」。 – 2012-03-15 18:13:24

+0

「你的第三行不會改變m本身,但是m指向的內容」可能對讀者有點不清楚。更明確地說:「第三行從指向一件事物(d ['m'])改變爲指向另一件事物([2,3])。」 – 2012-03-15 18:18:49

5

Ethan Furman沒有解釋如何Python的內部工作非常出色,我就不再重複了。

由於m確實代表字典內的列表,因此您可以對其進行修改。你不能將它重新分配給新的東西,當你使用=將它等同於一個新的分片時會發生什麼。

要切掉列表的第一個元素,例如:

>>> m[0:1] = [] 
>>> d 
{'m': [2, 3]} 
+4

我討厭開車通過downvotes,如果我做錯了,我想找出原因。這個答案已經在Python 2.7中使用推薦的習慣用法進行了測試:http://docs.python.org/library/stdtypes.html#mutable-sequence-types – 2012-03-15 17:56:42

+0

我認爲這是一個很好的見解Mark,我不知道爲什麼它被降低了... – 2012-03-15 18:14:22

+2

要從列表中刪除項目或切片,我通常更喜歡更明確的'del m [0]'。當然,這是一種風格偏好,我不知道爲什麼有人低調。我的猜測是,許多看似隨機的降價是由於智能手機的顯示屏太小造成的。 – 2012-03-15 21:01:08

4

在蟒一切都通過引用

在Python,一切的引用,所述引用得到價值傳遞。

如果你想使用這些條款。但是這些術語使事情變得更難理解。

更簡單:在Python中,變量是對象的名稱。 =用於更改名稱引用的對象。左側可以引用現有對象的一部分,在這種情況下,通過替換該部分來更改整個對象。這是因爲該對象反過來並不真正包含它的部分,而是包含更多的名稱,這可能導致開始引用不同的事物。

那麼什麼時候是一個新的對象創建?

創建對象時會創建對象(通過使用類構造函數,或者通過輸入文字,使用具有文字表示的內置類型)。我不明白這與你的其他問題有什麼關係。

m = m[1:] # m changes its reference to the new sliced list 

是的,當然。現在m是指評估m[1:]的結果。

edits m but not d (I wanted to change d) 

是的,當然。爲什麼它改變d?這不是某種魔術,而僅僅是評估d['m']的結果。兩條線都發生了完全相同的事情。

讓我們來看一個更簡單的例子。

m = 1 
m = 2 

這是否導致1成爲2?不,當然不。整數是不變的。但同樣的事情正在發生:m被命名爲一件事,然後命名另一件事。

或者,換句話說:如果「引用」按照您期望的方式工作,那麼行m = m[1:]將是遞歸的。你期望它的意思是「你看到的任何地方m,把它看作是m[1:]」。那麼,在這種情況下,m[1:]實際上意味着m[1:][1:],那麼這將意味着m[1:][1:][1:]