此示例摘自15:30的this视频:
x = 1, [2], 3
x[1] += [20]
由于某种原因,它发出一个
TypeError
(“ tuple”对象不支持项目分配),但是成功了,所以现在print(x) # (1, [2, 20], 3)
即如果您在repl中执行上述操作,那么它就可以正常工作。要在脚本中看到相同的效果,请使用
x = 1, [2], 3
try:
x[1] += [20]
except TypeError as e:
print(e)
print(x)
如何解释这种行为?好像列表对象本身首先被突变(成功),然后尝试将该列表重新分配给“名称”
x[1]
的尝试,然后引发异常。但是,为什么Python会在可变类型上尝试+=
的(冗余)重新分配? 最佳答案
其实你是对的。这正是python所做的。+=
运算符仅使用魔术方法__iadd__
。所以这段代码:
a_list = []
a_list += [1]
等效于:
a_list = []
a_list = a_list.__iadd__([1])
__iadd__
方法通常会修改对象并返回它,以便此分配有效,这就是代码中所发生的事情。您的代码等效于:x = 1, [2], 3
try:
x[1] = x[1].__iadd__([20])
except TypeError as e:
print(e)
print(x)
希望现在您能看到问题所在。
__iadd__
调用按预期方式工作并修改了列表,但是随后您尝试将其重新分配给不允许的元组的第二个元素。至于为什么要这样实现:您是否注意到我在上面强调了“通常”这个词。当您在自己的类中实现此方法时,不必返回您使用的同一对象。您可以退还其他东西。这就是为什么必须重新分配的原因。为什么要这样做是一个不同的问题,但是在python中,如果您尝试尝试,几乎可以破坏所有内容。
您的问题实际上在python FAQ中。我建议您阅读它,并阅读有关augmented assignments的更多信息。