In the vast majority of the cases
y *= <expr>
is the same as
y = y * <expr>
but in the general case, it is interpreted as:
y = imul(y, <expr>)
which is then equivalent to:
y = y.__imul__(<expr>)
if y
's type overrides __imul__
.
This means that if y
's type overrides the inplace multiplication operator, y*=<expr>
is performed inplace, while y=y*<expr>
is not.
EDIT
It might not be immediately clear why the assignment is needed, i.e. why it is intrepreted as y = imul(y, <expr>)
, and not just imul(y, <expr>)
.
The reason is that it makes a lot of sense for the following two scenarios to give the same result:
c = a * b
and
c = a
c *= b
Now, this of course works if a
and b
are of the same type (e.g. floats, numpy arrays, etc.), but if they aren't, it is possible for the result of the operation to have the type of b
, in which case the operation cannot be an inplace operation of a
, thus the result needs to be assigned to a
, in order to achieve the correct behavior.
For example, this works, thanks to the assignment:
from numpy import arange
a = 2
a *= arange(3)
a
=> array([0, 2, 4])
Whereas if the assignment is dropped, a
remains unchanged:
a = 2
imul(a, arange(3))
=> array([0, 2, 4])
a
=> 2
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…