关于python:x+=y和x=x+y之间的区别

The difference between x += y and x = x + y

本问题已经有最佳答案,请猛点这里访问。

我有这个python代码

1
2
3
4
5
x = [1, 2, 3]
y = x
x += [4]
>>> print(y)
[1, 2, 3, 4]

所以,这是因为x is yTrue,如果我改变x,我就改变y

但当我这样做的时候:

1
2
3
4
5
x = [1, 2, 3]
y = x
x = x + [4]
>>> print(y)
[1, 2, 3]

1
2
>>> id(x) == id(y)
False

我想知道有什么区别。我以为x += 1x = x+1的缩写,但显然有区别。

我更困惑的是,当我试着把上面的内容串起来的时候:

1
2
3
4
5
6
name = 'John'
name_2 = name
name += ' Doe'

>>> print(name_2)
'John'

所以我认为+=的效果取决于左边的物体,它是否可变?


对象"在左边"处理操作符(通常,请参见r-operator表单);在这种情况下,它是一个就地操作符。

10.3.2. Inplace Operators

Many operations have an"in-place" version. Listed below are functions providing a more primitive access to in-place operators than the usual syntax does; for example, the statement x += y is equivalent to x = operator.iadd(x, y) ..

实际结果由"x"对象确定,如果它处理__iadd__(例如,随列表而变)或仅处理__add__(例如,新的结果对象,如字符串),则选择要使用的协议以及为分配返回的值由operator.iadd它的elf1决定。

因此,x += y ~~ x = x + y的简写仅适用于某些对象,尤其是那些不可变的对象,并且[仅]实现__add__

看看python就地操作函数与标准操作函数有什么不同?

1在语义上,operator.iadd函数的工作原理如下:

1
2
3
4
5
6
if x.__iadd__:
    x.__iadd__(y)        # side-effect performed on x,
    return x             # returns original-but-modified object
else
    return x.__add__(y)  # return new object,
                         # __add__ should not have side-effects

正如@brenbarn所说,如果左侧对象是可变的,它将执行就地操作。否则,将返回一个新副本,因为它已被复制,所以它们的ID将不再匹配。

在背景中,它类似于这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> import copy
>>> y = [1,2,3]
>>> x = y
>>> x+=[4]
>>> y
[1, 2, 3, 4]
>>> x = copy.copy(y) #perhaps even a deepcopy()? Don't know.
>>> y
[1, 2, 3, 4]
>>> x
[1, 2, 3, 4]
>>> x += [5]
>>> y
[1, 2, 3, 4]
>>> x
[1, 2, 3, 4, 5]

编辑1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class test():
    def __init__(self, ll):
        self.a = ll
    def __add__(self, other):
        return test(ll=self.a+other.a)

>>> a = test([[1,2],[3,4]])
>>> a.a
[[1, 2], [3, 4]]
>>> x = test([[1,2],[3,4]])
>>> x += a
>>> x.a
[[1, 2], [3, 4], [1, 2], [3, 4]]
>>> a.a
[[1, 2], [3, 4]]
>>> x.a[2][0] = 7
>>> x.a
[[1, 2], [3, 4], [7, 2], [3, 4]]
>>> a.a
[[7, 2], [3, 4]]