記錄一個python裡面很神奇的操作,對一個包含列表的元組進行增量賦值,成功賦值但還報錯
阿新 • • 發佈:2019-02-09
記錄一個python裡面很神奇的操作
今天記錄一個很神奇的操作。關於序列的增量賦值。如果你很熟悉增量賦值,你也不妨看下去,我想說的是有關於增量賦值和元組之間一種神奇的操作。來自 《流暢的Python》 一書,讓我們更加深入地瞭解裡面的原理
神奇的操作
>>>t = (1,2,[30,40])
>>>t[2] += [50,60]
上面這段程式碼會出現什麼樣的情況
a. t會變成(1,2,[30,40,50,60])
b. 因為tuple不支援對它的元素賦值,所以會丟擲TypeError異常
c. 以上兩個都不是
d. a和b都是對的
大多數人都會認為b是正確的,本書的作者也是這麼認為的,但是實際上呢?卻是選 b
不要疑惑,就是這樣,既報錯,又成功進行了修改
首先講一下增量賦值
我們使用增量賦值運算子 += 和 *= 等增量賦值運算子的時候(用 += 舉例),使用的是背後的特殊方法 __iadd__,如果沒有實現這個方法則會退而求其次,使用 __add__ .
兩者的區別是什麼?
用列表舉例 a+=b,使用 __add__ 的話就像是使用了a.extend(b)
,如果使用 __add__ 的話,則是 a = a+b
,前者是直接在原列表上進行擴充套件,而後者是先從原列表中取出值,在一個新的列表中進行擴充套件,然後再將新的列表物件返回給變數,顯然後者的消耗要大些。
繼續將那個神奇的操作
既然我們瞭解了變數賦值,那麼我們就可以更深入一些了。
t[2] += [50,60] 實現原理:
1. 將t[2]的值,存入TOS(Top Of Stack 棧的頂端)。
2. 計算TOS +=b 。這一步可以完成,是因為TOS指向的是一個列表(可變物件)。
3. t[2] = TOS 賦值。這一步失敗,並且報錯,因為t是不可變的元組
我們可以通過python tutor這個網站去找到裡面執行的詳細過程