譬如有兩個 list a 和 b,使用 a.extend(b) 和 a += b 有什麼相同或不同?有沒有什麼 general 的 best practice for using one rather than the other?
其實在這個情境下,這兩個用法幾乎一樣。它們都會直接 in-place 的修改 a,把 b 裡面的元素加到 a 的後面
+=會呼叫 list 的.__iadd__()來做 in-place 的修改- 所以在這個情境下,
b可以是任何 iterable,譬如[] += {}會得到[] - 假如用
+=的是 immutable 的 type,Python 發現沒有.__iadd__(),接著就會呼叫它的.__add__(),此情況下a += b等同於a = a + b
- 所以在這個情境下,
+=不能用在 tuple 裡的 list,但.extend()可以- 雖然說
+=所呼叫的.__iadd__()是 in-place 修改,做完後a的 reference 還是會一樣,但過程中還是會以某種方式動到 reference,只是最後會有個 reassign 給自己的動作[註1],所以會有一樣的 reference
- 雖然說
+=不能用在 non-local variable,但.extend()可以+=不能 chain function call, 但.extend()可以- 兩者速度依不同情況稍有差異
結論
可以都用 .extend() 就好,consistency 也是一個重點。對於有差別的部分,一般情況下速度的差異可以忽略,其他的差別都是 .extend() 比較好,而且它在語意上的描述也也更貼切。
參考資料:
Concatenating two lists - difference between ‘+=’ and extend()
What is the difference between Python’s list methods append and extend?
註1:
l1 += l2andl1.extend(l2)ultimately execute the same code (thelist_extendfunction inlistobject.c). The only differences are: 1.+=reassignsl1(to itself forlists, but the reassignment supports immutable types that aren’t the same object after), which makes it illegal ifl1is actually an attribute of an immutable object; for example,t = ([],),t[0] += lstwould fail, whilet[0].extend(lst)would work. 2.l1 += l2uses dedicated bytecodes, whilel1.extend(l2)uses generalized method dispatch; this makes+=faster thanextend.