2012-12-16 143 views
6

在Python(2.7)中發現了一個前所未有的有趣的事情。擴展奇怪行爲的列表

此:

a = [] 
a += "a" 

不工作,結果是:

>>> a 
>>> ["a"] 

a = [] 
a = a + "a" 

>>> TypeError: can only concatenate list (not "str") to list 

有人可以解釋爲什麼嗎?感謝您的回答。

+0

'+'和'+ ='是不同的操作,即使它們在許多情況下似乎都是一樣的。 –

+1

'+ ='在Python列表(inplace add)中的行爲類似於extend(),另一個稱爲二進制添加。 –

回答

11

Python區分++=運算符,併爲這些運算符提供單獨的鉤子; __add____iadd__list()類型僅爲後者提供了不同的實現。

列表分別實現這些效率更高; __add__必須返回一個全新的列表,而__iadd__只能延伸self,然後返回self

在C代碼中,__iadd__list_inplace_concat()實現,該代碼簡單地稱爲listextend(),或者在Python代碼中爲[].extend()。後者通過設計需要任何序列。

另一方面,__add__方法,由C代表list_concat,只需要一個list作爲輸入,可能出於效率的原因;它可以直接在內部C數組上循環並將項目複製到新列表中。

總之,原因__iadd__接受任何序列是因爲當執行PEP 203(增強添加提案)時,對於列表,最簡單的方法是重用.extend()方法。

+0

謝謝,Martijn,這是我正在尋找的答案。 – alexvassel

9

如果a是一個列表,a + x只有工作,如果x也是名單,而a += x適用於任何可迭代x

下可能有助於理解:

In [4]: a = [] 

In [5]: a += "abc" 

In [6]: a 
Out[6]: ['a', 'b', 'c'] 

的關鍵是,"a"和​​是可迭代的,這是什麼讓他們對+=右手邊使用。

這對+不起作用,因爲後者要求兩個操作數的類型相同(請參閱manual)。

編寫使用+同樣的事情,你必須展開迭代:

In [7]: a = [] 

In [8]: a = a + list("abc") 

In [9]: a 
Out[9]: ['a', 'b', 'c'] 

換句話說,+=當應用於列表是更普遍比+

+0

問題是關於'lst + = iterable'和'lst + iterable'之間的*差*。 –

+0

它沒有解釋爲什麼你不能連接列表和迭代。 –

+0

@MartijnPieters:好的。查看最新的答案。 – NPE