“ for”循环中i = i + 1和i + = 1有什么区别?
我今天发现了一件奇怪的事情,想知道是否有人可以阐明其中的区别?
import numpy as np
A = np.arange(12).reshape(4,3)
for a in A:
a = a + 1
B = np.arange(12).reshape(4,3)
for b in B:
b += 1
运行完每个for
循环后,A
没有改变,但是B
在每个元素中添加了一个。我实际上使用该B
版本在for
循环内写入初始化的NumPy数组。
-
不同之处在于,一个修改数据结构本身(就地操作),
b += 1
而另一个仅 重新分配 变量a = a + 1
。
仅出于完整性考虑:
x += y
是 不是总是 做就地操作,有(至少)三种例外情况:-
如果
x
没有实现 的__iadd__
则方法的x += y
声明仅仅是一个速记x = x + y
。如果x
是类似的情况就是这种情况int
。 -
如果
__iadd__
返回NotImplemented
,Python将退回到x = x + y
。 -
从
__iadd__
理论上讲,该方法可以实现为无法正常运行。但是,这样做真的很奇怪。
发生时,您的
b
s是numpy.ndarray
实现__iadd__
并返回自身的,因此您的第二个循环就地修改了原始数组。这些[
__i*__
]方法称为实现增强算术分配(+=
,-=
,*=
,@=
,/=
,//=
,%=
,**=
,<<=
,>>=
,&=
,^=
,|=
)。这些方法应尝试就地执行操作(修改self)并返回结果(可以是,但不一定是self)。如果未定义特定方法,则扩展分配将退回到常规方法。例如,如果x是具有__iadd__()
方法的类的实例,x += y
则等效于x = x.__iadd__(y)
。否则,将x.__add__(y)
与和y.__radd__(x)
一起评估x + y
。在某些情况下,扩充分配可能会导致意外错误(请参见为什么a_tuple[i] += ["item"]
加法有效时会引发异常?),但实际上,该行为是数据模型的一部分。 -