In the vast majority of cases
y *= <expr>
coincides with
y = y * <expr>
but in general, it is interpreted as:
y = imul(y, <expr>)
which is then equivalent:
y = y.__imul__(<expr>)
if y overrides the __imul__ type.
This means that if type y overrides the inplace multiplication operator, y*=<expr> is executed inplace, and y=y*<expr> is not.
EDIT
It may not be immediately clear why an appointment is required, i.e. why it is interpreted as y = imul(y, <expr>) , and not just imul(y, <expr>) .
The reason is that for the following two scenarios it makes sense to make the same result:
c = a * b
and
c = a c *= b
Now this, of course, works if a and b same type (for example, float, numpy array, etc.), but if it is not, they are of type b , in which case the operation cannot be an inplace a operation, therefore To achieve proper behavior, the result must be assigned a .
For example, this works thanks to the purpose of:
from numpy import arange a = 2 a *= arange(3) a => array([0, 2, 4])
If the assignment is omitted, a remains unchanged:
a = 2 imul(a, arange(3)) => array([0, 2, 4]) a => 2