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