2014-01-26 67 views
3

我試圖修改元組中的列表,append方法工作,而+=運算符還有一個異常提出說元組不能成爲。?修改我知道一個元組是不可改變的,但我並不想發生變異它爲什麼發生這種情況獲取「元組」對象的變異元組不支持項目分配「

In [36]: t=([1,2],) 

In [37]: t[0].append(123) 

In [38]: t 
Out[38]: ([1, 2, 123],) 

In [39]: t[0]+=[4,5,] 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-39-b5b3001fbe03> in <module>() 
----> 1 t[0]+=[4,5,] 

TypeError: 'tuple' object does not support item assignment 

In [40]: t 
Out[40]: ([1, 2, 123, 4, 5],) 
+0

另請參見[官方解釋在Python FAQ](http://docs.python.org/2/faq/programming的.html#爲什麼 - 不 - 一個元組-I-項目加註-AN-異常時最加成作品)。 – user2357112

+0

@ user2357112,謝謝〜並感謝下面的所有答案!我認爲必須有這個答案,只是不知道如何描述和谷歌這一點;) – zhangxaochen

回答

6

+=是就地添加運算符。它確實件事:

  • 它調用obj.__iadd__(rhs)給該對象的機會變異就地對象。
  • 它重新引用任何obj.__iadd__(rhs)調用返回的引用。

通過在存儲在元組中的列表上使用+=,第一步成功; t[0]列表在原地進行了更改,但重新綁定t[0]t[0].__iadd__的返回值的第二步失敗,因爲元組是不可變的。

是需要的,後一步驟來支持相同的運營商在兩個可變和不可變的對象:

>>> reference = somestr = 'Hello' 
>>> somestr += ' world!' 
>>> somestr 
'Hello world!' 
>>> reference 
'Hello' 
>>> reference is somestr 
False 

這裏一個不可變的字符串被添加到,並somestr是反彈到對象,因爲字符串是不可改變的。

>>> reference = somelst = ['foo'] 
>>> somelst += ['bar'] 
>>> somelst 
['foo', 'bar'] 
>>> reference 
['foo', 'bar'] 
>>> reference is somestr 
True 

下面列表中就地被改變,somestr是反彈到同一對象,因爲list.__iadd__()可以改變就地列表對象。

augmented arithmetic special method hooks documentation

這些方法稱爲實現增強的算術作業(+=-=*=/=//=%=**=<<=>>=&=^=|=)。這些方法應該嘗試就地操作(修改self)並返回結果(可能是,但不一定是,self)。

工作,在這裏是調用t[0].extend()代替:

>>> t = ([1,2],) 
>>> t[0].extend([3, 4, 5]) 
>>> t[0] 
[1, 2, 3, 4, 5] 
+1

+1提「機會」 – zhangxaochen

4

因爲t[0] += [4,5,]被解釋爲:

t[0] = t[0].__iadd__([4,5,]) 

t[0]__iadd__([4,5])成功,而t[0] = ..失敗。


list.__iadd__擴展名單,並返回自己。

>>> lst = [0] 
>>> lst2 = lst.__iadd__([1]) 
>>> lst 
[0, 1] 
>>> lst2 
[0, 1] 
>>> lst is lst2 
True 
+0

+1爲'並返回自己',thx – zhangxaochen

1

其實你改變元組:

+運營商列表中創建一個新的列表,並試圖通過用新的替換舊列表變異的元組。 append修改元組中的列表,因此它起作用。

+0

我不認爲我**取代**因爲'l = [1,];打印id(l);升+ = [3];打印id(l)'打印相同的id。 – zhangxaochen

+0

@zhangxaochen:在可變對象上的原地添加有兩件事:變異對象並返回'self',以便引用可以重新綁定。 –

+0

+1快速回復;) – zhangxaochen

1

當我們說元組是不可變的,這意味着一個元組(它是對其他對象的引用)的元素不能被改變(讀爲,不能被引用其他對象)。

所以,當你說,

t[0].append(123) 

你是不是在索引0改變元素,引用其他對象。相反,您正在對同一個對象進行更改,根據元組完全可以。

當你說,

t[0] += [4,5,] 

Python的內部調用__iadd__(代表就地補充)方法,這可以理解這樣

t[0] = t[0] + [4,5,] 

這意味着,我們採取了對象t[0],將其與[4,5,]一起添加以獲得新對象,並且該新對象正在被轉讓給返回到t[0]。現在我們試圖改變元組(使元組的元素引用其他某個對象)。

這就是爲什麼你在後一種情況下看到

TypeError: 'tuple' object does not support item assignment 

+0

+1 thx;)。 – zhangxaochen

相關問題