增量賦值運(yùn)算符有 += 和 *=。+= 背后的特殊方法是 __iadd__,如果一個(gè)類沒有實(shí)現(xiàn) __iadd__ 方法,Python 會(huì)退一步調(diào)用 __add__ 方法。這兩個(gè)方法的區(qū)別在于,__iadd__ 為就地改動(dòng),不會(huì)改變?cè)档膬?nèi)存地址,而 __add__ 方法會(huì)得到一個(gè)新對(duì)象。
考慮下面一個(gè)表達(dá)式:
a += b
如果 a 實(shí)現(xiàn)了 __iadd__ 方法,a 會(huì)就地改動(dòng)(內(nèi)存地址不變)。如果 a 沒有實(shí)現(xiàn) __iadd__ 方法,那么 a += b 這個(gè)表達(dá)式的效果就變得跟 a = a + b 一樣了,生成一個(gè)新的對(duì)象賦給 a。
總體來講,可變序列一般都實(shí)現(xiàn)了 __iadd__ 方法,因此 += 是就地加法,而不可變序列根本就不支持這個(gè)操作。
*= 和 += 一樣,只是背后的特殊方法為 __imul__。
a = [1, 2, 3] b = [4, 5, 6]print("id(a) = %d" % id(a)) a += bprint("id(a) = %d" % id(a)) c = [1, 2, 3]print("id(c) = %d" % id(c)) c = c + bprint("id(c) = %d" % id(c)) d = (1, 2, 3)print("id(d) = %d" % id(d)) d *= 2print("id(d) = %d" % id(d))
運(yùn)行結(jié)果如下:
id(a) = 1298277978824 id(a) = 1298277978824 id(c) = 1298277978696 id(c) = 1298277978632 id(d) = 1298277972872 id(d) = 1298277136616
了解了序列的增量賦值,我們來看 Leonardo Rochael 在 2013 年的 Python 巴西會(huì)議上提到的謎題:
t = (1, 2, [30, 40]) t[2] += [50, 60]
A. t 變成 (1, 2, [30, 40, 50, 60])
B. 因?yàn)?tuple 不支持對(duì)它的元素賦值,所以會(huì)拋出 TypeError 異常
C. 以上兩個(gè)都不是
D. A 和 B 都是對(duì)的
估計(jì)很多人會(huì)跟我一樣選 B,但其實(shí)答案是 D。在控制臺(tái)運(yùn)行代碼,顯示結(jié)果如下:
總結(jié):
1、對(duì)不可變序列進(jìn)行重復(fù)拼接操作的話,效率會(huì)很低,因?yàn)槊看味家陆ㄒ粋€(gè)序列,然后把原來序列中的元素復(fù)制到新的序列里,然后再追加新的元素。
2、不要把可變對(duì)象放在元組里面。
3、增量賦值不是一個(gè)原子操作,我們剛才也看到了,它雖然拋出了異常,但 t 的值還是改變了。
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com