2010-01-08 21 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本身)来重述这个问题,它可能会变得更清晰。