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

Python赋值运算符不同于非赋值运算符,python,assignment-operator,Python,Assignment Operator,我面对这种奇怪的行为,我找不到解释 MWE: l=[1] l+={'a':2} L [1,‘a’] l+{'B':3} 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:只能将列表(而不是“dict”)连接到列表 基本上,当我+=时,python不会引发错误并将键附加到列表中,而当我只计算+时,我会得到预期的类型错误 注意:这是Python3.6.10l+=…实际上是在调用对象。当l是可变的 原因(正如@DeepSpace在他的评论中解释的)是,当您执行l+={'a':

我面对这种奇怪的行为,我找不到解释

MWE:

l=[1]
l+={'a':2}
L
[1,‘a’]
l+{'B':3}
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:只能将列表(而不是“dict”)连接到列表
基本上,当我
+=
时,python不会引发错误并将键附加到列表中,而当我只计算
+
时,我会得到预期的
类型错误


注意:这是Python3.6.10

l+=…
实际上是在调用
对象。当
l
是可变的

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


(见附件)


与调用
对象的
+
不同。\uuu添加(self,other)


因此,正如作者所说,这不是一个bug。当你做
a+=b
的时候,就像
b
来到
a
的家里,改变它原来的样子作者所说的是,当你做
a+b
时,无法决定哪种风格会被优先考虑。没有人知道
a+b
的结果会去哪里,除非你执行它。所以你无法决定这是谁的风格。如果是
a
样式,则为
[1,'a']
,如果是
b
样式,则为错误。因此无法决定谁将获得优先权
。所以我个人不同意这种说法。因为当您接受调用堆栈时,
a
位于比
b
更高的位置。当有一个像
a+b
这样的表达式时,首先调用
a.\uuu add\uu(self,other)
如果
a.\uu add\uuu
未实现的
(在本例中是实现的)。然后你调用
a.\uuu radd\uuu(self,other)
。这意味着调用
other.\uuuu add\uuu
在本例中为
b.\uu add\uuu
。我是根据调用堆栈的位置来讲述这一点的,python社区可能有更重要的原因来这样做。

检查此项,请参见-“将列表与迭代器连接时结果不一致”。另请注意,
+=
等都被称为PEP介绍的“增强分配”。这很奇怪,@alkasm的bug链接有一个很好的解释<代码>当a是可变的时,a+=b会就地更新它,因此没有歧义:a的类型不能更改。当您选择a+b时,在选择结果类型时,没有理由认为a比b更值得。
@ChrisDoyle这正是原因所在。这不是一个“bug”,它是一种防止解释器猜测的机制。这也应该解释原因
l+=…
就地更新
l
,因此结果的类型是明确的(=
l
的类型)
l+…
是不明确的,因为它不在适当的位置,所以生成的新对象的类型不清楚(应该是
l
类型还是
?)当然!我在回答中加了这个。
l+=…
在-place@seralouk,您是否介意分享您使用的工具来确定调用了哪个函数?Inspect、pdb等?文档:和一些编程知识(如字典)是可变的。@DeepSpace推理是有道理的,但
\uuuuuuuidd\uuuuuuu
不保证返回相同的对象。请参见
编号+=2
。此外,来自文档:这些方法应该尝试就地执行操作(修改self)并返回结果(可能是,但不一定是self)
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
l = [1]
l = l.__iadd__({'a': 2})
l
#[1, 'a']
l + {'B': 3}
TypeError: can only concatenate list (not "dict") to list