什么时候"i + = x"?与"i = i + x"不同在Python中? [英] When is "i += x" different from "i = i + x" in Python?

查看:81
本文介绍了什么时候"i + = x"?与"i = i + x"不同在Python中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人告诉我+=的作用可能不同于i = i +的标准表示法. 是否存在i += 1i = i + 1不同的情况?

I was told that += can have different effects than the standard notation of i = i +. Is there a case in which i += 1 would be different from i = i + 1?

推荐答案

这完全取决于对象i.

+=调用 __iadd__方法(如果存在-如果不存在则返回__add__),而+调用 __add__方法 1

+= calls the __iadd__ method (if it exists -- falling back on __add__ if it doesn't exist) whereas + calls the __add__ method1 or the __radd__ method in a few cases2.

从API的角度来看,应该使用__iadd__来修改可变对象 (返回已变异的对象),而__add__应该返回一个 new实例.对于 immutable 对象,这两个方法都返回一个新实例,但是__iadd__会将新实例放置在当前名称空间中,并具有与旧实例相同的名称.这就是为什么

From an API perspective, __iadd__ is supposed to be used for modifying mutable objects in place (returning the object which was mutated) whereas __add__ should return a new instance of something. For immutable objects, both methods return a new instance, but __iadd__ will put the new instance in the current namespace with the same name that the old instance had. This is why

i = 1
i += 1

似乎增加了i.实际上,您获得了一个新的整数并将其"i之上"分配-丢失了对旧整数的一个引用.在这种情况下,i += 1i = i + 1完全相同.但是,对于大多数易变的物体,情况就不同了:

seems to increment i. In reality, you get a new integer and assign it "on top of" i -- losing one reference to the old integer. In this case, i += 1 is exactly the same as i = i + 1. But, with most mutable objects, it's a different story:

作为一个具体示例:

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.

notice how in the first example, since b and a reference the same object, when I use += on b, it actually changes b (and a sees that change too -- After all, it's referencing the same list). In the second case however, when I do b = b + [1, 2, 3], this takes the list that b is referencing and concatenates it with a new list [1, 2, 3]. It then stores the concatenated list in the current namespace as b -- With no regard for what b was the line before.

1 在表达式x + y中,如果未实现x.__add__x.__add__(y)返回NotImplemented xy具有不同的类型,然后x + y尝试调用 y.__radd__(x) .因此,如果您拥有

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

如果Foo未实现__add____iadd__,则此处的结果与

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)

2 在表达式foo_instance + bar_instance中,如果bar_instance的类型是foo_instance.__add__的子类,则会在foo_instance.__add__ 之前尝试bar_instance.__radd__. foo_instance的类型(例如issubclass(Bar, Foo)).这样做的合理性是因为Bar在某种意义上是比Foo更高级别"的对象,因此Bar应该可以选择替代Foo的行为.

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.

这篇关于什么时候"i + = x"?与"i = i + x"不同在Python中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆