2010-01-08 52 views
4
>>> c = [1, 2, 3] 
>>> print(c, id(c)) 
[1, 2, 3] 43955984 
>>> c += c 
>>> print(c, id(c)) 
[1, 2, 3, 1, 2, 3] 43955984 
>>> del c 
>>> c = [1, 2, 3] 
>>> print(c, id(c)) 
[1, 2, 3] 44023976 
>>> c = c + c 
>>> print(c, id(c)) 
[1, 2, 3, 1, 2, 3] 26564048 

有什麼區別?是+ =和+不應該只是語法糖?+和+ =運算符是不同的?

+1

你的例子清楚地表明它們不是。 + =明確地加入到這個對象中,並且x = a + b(即使a = b = x)顯然會創建一個新結果並將其分配給LHS。我認爲,檢查每個添加項是否是一個簡單的添加(如上所述)並將其優化爲+ =是反作用的。 – Lazarus 2010-01-08 11:46:45

+0

爲什麼downvote?我承認標題可能會更好,但問題本身是非常有效的 – Kimvais 2010-01-08 11:55:09

+0

這個問題有一些很好的列表連接操作的附加信息http://stackoverflow.com/questions/2022031/python-append-vs-operator-on-lists -why-do-these-give-different-results – Kimvais 2010-01-08 12:01:34

回答

13

docs explain it very well,我想:

__iadd__()
這些方法稱爲實現增強的算術作業(+=, -=, *=, /=, //=, %=, **=, <<=, >>=, &=, ^=, |=)。 這些方法應嘗試就地操作(修改self)並返回結果(可能是,但不一定是,self)。如果未定義特定的方法,則增強的分配將回到常規方法。例如,要執行語句x += y,其中x是具有__iadd__()方法的類的實例,則調用x.__iadd__(y)

+=設計用於實施就地修改。在簡單添加的情況下,創建新對象並使用已用名稱(c)進行標記。

此外,您會注意到+=運算符的這種行爲僅可能是由於列表的可變性。整數 - 一個不可變型 - 不會產生相同的結果:

>>> c = 3 
>>> print(c, id(c)) 
3 505389080 
>>> c += c 
>>> print(c, id(c)) 
6 505389128 
+0

另一點是評估/優先順序。在'c = c + c'中'c + c'在賦值'c ='之前被評估,其中'c + = c'本身沒有兩個不同的操作。 – Kimvais 2010-01-08 11:52:19

+0

這就是我說的:) – SilentGhost 2010-01-08 11:54:34

3

他們不一樣

C + = C的的C含量拷貝追加到C本身

C = C + C創建使用C新的對象+ C

1

+ =操作符追加第二列表到第一,但所述修飾是在就地,所以ID保持相同。

當您使用+時,會創建一個新列表,並且最終的「c」是一個新列表,因此它具有不同的ID。

雖然兩個操作的最終結果是相同的。

2

對於

foo = [] 

foo+=foofoo.extend(foo)(而不是foo = foo + foo

在第一種情況下,你只是追加列表的成員到另一個(而不是創建一個新的語法糖)。

id第二種情況發生了變化,因爲新列表是通過添加兩個列表而創建的。偶然的是,兩者都是相同的,並且結果被綁定到相同的標識符,而不是一次指向它們。

如果你用不同的列表(而不是c本身)來重述這個問題,它可能會變得更清晰。