Python中关于+=和=+的问题

今天在LintCode刷题的时候,看别人的题解发现了一个很费解(对于我来说)的东西;
题目:

题解:

其中的

for i in nums:
    self.sum += self.sum[-1] + i,

让我疑惑许久,于是开始各种寻找答案。

1、首先在编译器中debug,明白了 self.sum[-1] + i, 加逗号是为了让此表达式变成元组,将得到的结果添加到定义的self.num列表去;
2、继续在编译器中尝试,但是怎么都不行,因为在列表中使用 + 进行拼接,只支持列表间的组合,而sums[-1]和``` i ``都是int类型的;

>>> a = [6]
>>> a + (3,)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: can only concatenate list (not "tuple") to list

3、继续尝试尝试尝试,终于发现

>>> a = a + (3,)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: can only concatenate list (not "tuple") to list
>>> a += (3,)
>>> a
[1, 3]

为什么 + 和 += 不一样?经过搜索发现了一篇文章,解答了这个问题:https://justjavac.com/python/2013/03/11/if-x-is-list-why-does-x-ha-work-while-x-x-ha-throw-an-exception.html
总结:当在list中使用+时,两个操作对象都必须是列表,而使用+=时,相当于调用extend,extend() 函数用于在列表末尾一次性追加另一个序列中的多个值,其参数只需要是可迭代序列即可。

补充:
在python中,+=和=+还涉及到可变对象/不可变对象,记录一下。
所涉及知识如下:
1、可变对象:字典dict、列表list、集合set;不可变对象:字符串、数值(int、float)、元组tuple;
2、一般情况下,可变对象有__iadd__方法,不可变对象没有__iadd__方法,只有__add__方法(str是有__iadd__方法的,但仍会改变内存地址);
3、__iadd__方法直接在原地修改对象的值,不改变内存地址;而__add__方法返回一个新的对象,因此内存地址会改变;
4、如果一个类没有实现__iadd__方法,python会退而求其次调用__add__方法;
5、+=调用的魔法方法是__iadd__,而+(=+)调用的是__add__
因此,对于可变对象,=+操作调用__add__,会修改内存地址;+=操作调用__iadd__,不改变内存地址;对于不可变对象,没有__iadd__方法,=+和+=操作,都调用的__add__方法,因此内存地址都会改变。

参考资料:

https://zhuanlan.zhihu.com/p/115242988
https://blog.csdn.net/wangjunjie0817/article/details/85040077

posted @ 2022-02-10 15:01  hook_what  阅读(435)  评论(0编辑  收藏  举报