什么时候在Python中与“i = i + x”不同的是“i + = x”?

问题:

我被告知+=i = i +的标准符号有不同的效果。有没有i += 1i = i + 1不同的情况

回答:

这完全取决于对象i
 +=调用__iadd__ method(如果存在 – 如果不存在则返回__add__),而+调用__add__ method 1__radd__ method in a few cases 2
从API的角度看,__iadd__应该用于修改可变对象in place(返回被突变的对象),而__add__应该返回一个new instance的东西。对于immutable对象,这两个方法返回一个新的实例,但是__iadd__将新的实例放在与旧实例相同名称的当前命名空间中。这就是为什么

i = 1
i += 1

似乎递增i。实际上,您将获得一个新的整数,并将其分配给“i”,即丢失对旧整数的引用。在这种情况下,i += 1i = i + 1完全相同。但是,对于大多数可变对象,这是一个不同的故事:
作为具体的例子:

a = [1, 2, 3]
b = a
b += [1, 2, 3]
print a  #[1, 2, 3, 1, 2, 3]
print b  #[1, 2, 3, 1, 2, 3]

相比:

a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print a #[1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]

注意在第一个例子中,由于ba引用同一个对象,当我在b上使用+=时,实际上会改变b(而a也会看到这种改变) – 毕竟,它引用了相同的列表)。然而,在第二种情况下,当我执行b = b + [1, 2, 3]时,这就是b引用的列表,并将其与新的列表[1, 2, 3]连接起来。然后它将当前命名空间中的并置列表存储为b – 不考虑以前的行b
 1In the expression x + y, if x.__add__ isn’t implemented or if x.__add__(y) returns NotImplemented and x and y have different types, then x + y tries to call y.__radd__(x). So, in the case where you have
 foo_instance += bar_instance
 if Foo doesn’t implement __add__ or __iadd__ then the result here is the same as
 foo_instance = bar_instance.__radd__(bar_instance, foo_instance)
 2In the expression foo_instance + bar_instance, bar_instance.__radd__ will be tried before foo_instance.__add__ if the type of bar_instance is a subclass of the type of foo_instance (e.g. issubclass(Bar, Foo)). The rational for this is because Bar is in some sense a “higher-level” object than Foo so Bar should get the option of overriding Foo‘s behavior.

 
 Code问答: codewenda.com
Stackoverflow:When is “i += x” different from “i = i + x” in Python?

发表评论

电子邮件地址不会被公开。 必填项已用*标注

+ 68 = 74