x += y 和 x = x + y 的区别
The difference between x += y and x = x + y
我有这个python代码
x = [1, 2, 3]
y = x
x += [4]
>>> print(y)
[1, 2, 3, 4]
所以,这是因为 x is y
是 True
,如果我更改 x
,我会更改 y
但是当我这样做时:
x = [1, 2, 3]
y = x
x = x + [4]
>>> print(y)
[1, 2, 3]
和
>>> id(x) == id(y)
False
我想知道有什么区别。我以为 x += 1
是 shorthand for x = x+1
但显然肯定有区别。
我更困惑了,当我尝试上面的字符串时:
name = 'John'
name_2 = name
name += ' Doe'
>>> print(name_2)
'John'
所以我认为+=
的效果取决于左边的对象,是否可变?
“左边”的对象处理运算符(通常,参见 r-运算符形式);在这种情况下,它是 Inplace 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__
(例如,一个新的结果对象,与字符串一样)——选择使用哪个协议,以及分配给 return 的什么值,由 operator.iadd
本身 1[ 决定=37=].
因此 x += y ~~ x = x + y
的 shorthand 对于某些对象 仅 为真 - 特别是那些不可变且 [仅] 实现 __add__
的对象.
见How are Python in-place operator functions different than the standard operator functions?
1 从语义上讲,operator.iadd 函数的工作原理类似于:
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 将不再匹配。
在后台,它的运行类似于此:
>>> 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:
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]]
我有这个python代码
x = [1, 2, 3]
y = x
x += [4]
>>> print(y)
[1, 2, 3, 4]
所以,这是因为 x is y
是 True
,如果我更改 x
,我会更改 y
但是当我这样做时:
x = [1, 2, 3]
y = x
x = x + [4]
>>> print(y)
[1, 2, 3]
和
>>> id(x) == id(y)
False
我想知道有什么区别。我以为 x += 1
是 shorthand for x = x+1
但显然肯定有区别。
我更困惑了,当我尝试上面的字符串时:
name = 'John'
name_2 = name
name += ' Doe'
>>> print(name_2)
'John'
所以我认为+=
的效果取决于左边的对象,是否可变?
“左边”的对象处理运算符(通常,参见 r-运算符形式);在这种情况下,它是 Inplace 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 tox = operator.iadd(x, y)
..
实际结果由“x”对象决定,如果它处理__iadd__
(例如,像列表一样突变)或只是__add__
(例如,一个新的结果对象,与字符串一样)——选择使用哪个协议,以及分配给 return 的什么值,由 operator.iadd
本身 1[ 决定=37=].
因此 x += y ~~ x = x + y
的 shorthand 对于某些对象 仅 为真 - 特别是那些不可变且 [仅] 实现 __add__
的对象.
见How are Python in-place operator functions different than the standard operator functions?
1 从语义上讲,operator.iadd 函数的工作原理类似于:
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 将不再匹配。
在后台,它的运行类似于此:
>>> 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:
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]]