Python 赋值运算符不同于非赋值运算符

Python assignment operator differs from non assignment

我遇到过这种奇怪的行为,我找不到解释。

MWE:

l = [1]
l += {'a': 2}
l
[1, 'a']
l + {'B': 3}
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: can only concatenate list (not "dict") to list

基本上,当我 += python 不会引发错误并将密钥附加到列表时,而当我只计算 + 时,我得到预期的 TypeError.

注意:这是 Python 3.6.10

l += ... 实际上是在调用 object.__iadd__(self, other) 并在 lmutable 时修改对象 in-place

原因(正如@DeepSpace 在他的评论中解释的那样)是当您执行 l += {'a': 2} 时,操作仅在 l 到位且仅当 l 可变时更新。另一方面,操作 l + {'a': 2} 未就地完成,导致 list + dictionary -> TypeError.


(参见 here


l = [1]
l = l.__iadd__({'a': 2})
l
#[1, 'a']

与调用object.__add__(self, other)

+不同
l + {'B': 3}
TypeError: can only concatenate list (not "dict") to list

正如作者所说,这不是一个错误。当你做 a += b 时,就像 b 来到 a 的房子,并按照 a 喜欢的方式改变它。 作者所说的是,当您执行 a + b 时,无法决定优先考虑哪种风格。在你执行它之前,没有人知道 a + b 的结果会去哪里。所以你不能决定它会是谁的风格。如果是 a 风格就是 [1, 'a'] 风格,如果是 b 风格就是错误。因此无法决定谁将获得优先权。所以我个人不同意这种说法。因为当你调用堆栈时 ab 处于更高的位置。当有像 a + b 这样的表达式时,如果 a.__add__NotImplemented,则首先调用 a.__add__(self, other)(在这种情况下它已实现)。然后你打电话给a.__radd__(self, other)。这意味着在这种情况下调用 other.__add__ b.__add__。我是根据调用堆栈的位置来说明这一点的,python 社区可能有更重要的理由这样做。