Python language reference 3.3.7: Emulating numeric types says this of the __rXXX__ magic methods:
These methods are called to implement the binary arithmetic operations (+, -, *, /, //, %, divmod(), pow(), **, <<, >>, &, ^, |) with reflected (swapped) operands. These functions are only called if the left operand does not support the corresponding operation and the operands are of different types. For instance, to evaluate the expression x - y, where y is an instance of a class that has an __rsub__() method, y.__rsub__(x) is called if x.__sub__(y) returns NotImplemented.
Thus for your case: at first for a * b Python tries to call a.__mul__(b). If this method does not exist or returns NotImplemented, Python calls b.__rmul__(a). If that returns a value that is not NotImplemented, that shall be the result of multiplication.
That way only one of a or b needs to support multiplication by the other.
In this specific case of multiplying a list (or any sequence) by an integer, it is slightly more efficient to do [1, 2, 3] * 2 than 2 * [1, 2, 3]; both give the same result, but [1, 2, 3] * 2 calls list.__mul__ first:
>>> [1,2,3].__mul__(2)
[1, 2, 3, 1, 2, 3]
The latter calls int.__mul__ first, which, given a list, returns NotImplemented:
>>> (2).__mul__([1,2,3])
NotImplemented
Then Python proceeds to calling [1, 2, 3].__rmul__(2):
>>> [1,2,3].__rmul__(2)
[1, 2, 3, 1, 2, 3]
And of course multiplication is not generally commutative; think about matrix multiplication