2016-08-21 42 views
11

我只是在解釋器中忙碌着,碰到一些我不明白的東西。當我創建一個列表作爲元素的元組,然後嘗試更新列表時,會發生一些奇怪的事情。例如,當我運行此:更新一個元組內的列表

tup = (1,2,3,[4,5]) 
tup[3] += [6] 

我得到:

TypeError: 'tuple' object does not support item assignment 

這正是我的預期。但是後來當我再次引用元組,我得到:

>>> tup 
(1, 2, 3, [4, 5, 6]) 

所以名單,其實是更新儘管蟒蛇拋出異常。這是如何運作的?我無法想象我真的想要做這樣的事情,但我仍然想知道發生了什麼。謝謝。

回答

27

這實際上記錄在Python docs

編輯:這是一個總結,以便這是一個更完整的答案。

  1. 當我們使用+=,Python會自動調用關於該項目的__iadd__魔術方法,然後使用在隨後的項目分配的返回值。
  2. 對於列表,__iadd__相當於在列表上調用extend,然後返回列表。
  3. 因此,當我們調用tup[3] += [6],它相當於:

    result = tup[3].__iadd__([6]) 
    tup[3] = result 
    
  4. 從#2,我們可以確定這相當於:

    result = tup[3].extend([6]) 
    tup[3] = result 
    
  5. 第一行呼籲extend成功在列表中,因爲列表是可變的,所以它會更新。但是,隨後的分配失敗,因爲元組是不可變的,並引發錯誤。
+2

我想這個答案會從另一個好處,那就是因爲擴展不僅僅是'tup [3] .__ iadd __([6])';它是'tup [3] = tup [3] .__ iadd __([6])''。 'list .__ iadd__'返回它正在變異的同一個對象是很方便的。 – zondo

+0

感謝您的文檔鏈接!這是一個很大的幫助。 –

+0

謝謝,我沒有在文檔中看到這一點。所以爲了確保我理解這個權利,基本上在我的例子中,列表被更新,因爲我只是在做tup [3] .__ iadd __([6]),然後python嘗試(並失敗)元組上的項目分配?所以我得到例外說它失敗了,但到那時我們已經更新了列表? –

相關問題