“for"循环中的 i = i + 1 和 i += 1 有什么区别?
我今天发现了一件奇怪的事情,想知道是否有人可以解释这里的区别?
I found out a curious thing today and was wondering if somebody could shed some light into what the difference is here?
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 数组.
After running each for
loop, A
has not changed, but B
has had one added to each element. I actually use the B
version to write to a initialized NumPy array within a for
loop.
区别在于一个修改数据结构本身(就地操作)b += 1
而另一个只是 重新分配变量a = a + 1
.
The difference is that one modifies the data-structure itself (in-place operation) b += 1
while the other just reassigns the variable a = a + 1
.
只是为了完整性:
x += y
并不总是进行就地操作,有(至少)三个例外:
x += y
is not always doing an in-place operation, there are (at least) three exceptions:
如果
x
没有实现__iadd__
方法,则x += y
语句只是x = x + y
的简写.如果x
类似于int
,就会出现这种情况.
If
x
doesn't implement an__iadd__
method then thex += y
statement is just a shorthand forx = x + y
. This would be the case ifx
was something like anint
.
如果 __iadd__
返回 NotImplemented
,Python 会回退到 x = x + y
.
If __iadd__
returns NotImplemented
, Python falls back to x = x + y
.
__iadd__
方法理论上可以实现为不工作.不过这样做真的很奇怪.
The __iadd__
method could theoretically be implemented to not work in place. It'd be really weird to do that, though.
碰巧你的 b
是 numpy.ndarray
,它实现了 __iadd__
并返回自身,所以你的第二个循环修改了原始数组-地方.
As it happens your b
s are numpy.ndarray
s which implements __iadd__
and return itself so your second loop modifies the original array in-place.
您可以在 模拟数字类型"的 Python 文档中阅读更多相关内容.
调用这些 [__i*__
] 方法来实现增广算术赋值(+=
, -=
, *=
、@=
、/=
、//=
、%=
、**=
, <<=
, >>=
, &=
, ^=
, |=
).这些方法应该尝试就地执行操作(修改 self)并返回结果(可以是但不一定是 self).如果未定义特定方法,则增广赋值回退到正常方法.例如,如果 x 是具有 __iadd__()
方法的类的实例,则 x += y
等价于 x = x.__iadd__(y)代码> .否则,将考虑
x.__add__(y)
和 y.__radd__(x)
,与对 x + y
的评估一样.在某些情况下,增强赋值可能会导致意外错误(请参阅 为什么 a_tuple[i] += ["item"]
当加法起作用时引发异常?),但这种行为实际上是数据模型的一部分.
These [
__i*__
] methods are called to implement the augmented arithmetic assignments (+=
,-=
,*=
,@=
,/=
,//=
,%=
,**=
,<<=
,>>=
,&=
,^=
,|=
). These methods should attempt to do the operation in-place (modifying self) and return the result (which could be, but does not have to be, self). If a specific method is not defined, the augmented assignment falls back to the normal methods. For instance, if x is an instance of a class with an__iadd__()
method,x += y
is equivalent tox = x.__iadd__(y)
. Otherwise,x.__add__(y)
andy.__radd__(x)
are considered, as with the evaluation ofx + y
. In certain situations, augmented assignment can result in unexpected errors (see Why doesa_tuple[i] += ["item"]
raise an exception when the addition works?), but this behavior is in fact part of the data model.