3

I assumed that @ was shorthand for the dot method. What motivated the design decision to block multiplication by an array with shape ()?

In [6]: a = np.ones((2,1))

In [7]: a.dot(1)
Out[7]:
array([[ 1.],
       [ 1.]])

In [8]: a @ 1
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-8-398cff4c0ec9> in <module>()
----> 1 a @ 1

ValueError: Scalar operands are not allowed, use '*' instead
0

1 Answer 1

6

@ is the infix operator for matmul, not dot (note that the two functions are not equivalent for higher-dimensional arrays (higher than 2D)).

No explicit reason for rejecting scalars as operands is stated in the documentation, but it seems probable that the motivation stems from PEP 0465 which originally proposed the introduction of @ as an infix operator for Python 3.5. From the 'semantics' section:

0d (scalar) inputs raise an error. Scalar * matrix multiplication is a mathematically and algorithmically distinct operation from matrix @ matrix multiplication, and is already covered by the elementwise * operator. Allowing scalar @ matrix would thus both require an unnecessary special case, and violate TOOWTDI ["There's Only One Way To Do It"].

Sign up to request clarification or add additional context in comments.

5 Comments

Funny that rule is something a Python developer would write, not a numpy one. The numpy approach is to turn the scalar into an array and proceed. Most numpy changes aren't ruled by peps.
I guess that PEP was written mainly with numerical libraries specifically in mind (NumPy chief among them). The author is Nathaniel J. Smith, who I think contributes frequently to NumPy's development.
@hpaulj: The PEP was pretty much written by numpy developers (in collaboration with other numerical libraries); python-dev mostly rubber-stamped it. You can see more of the history in the references at the bottom, or check that that text was present in the very first version that the upstream python developers saw.
@NathanielJ.Smith: Thanks for the link! That explains the last of my questions.
I guess as a further note with actual content :-): numpy in general doesn't just turn scalars into arrays willy-nilly; most operations follow some very simple deterministic rules. What dot does with scalars is weird -- it effectively promotes a scalar into a square matrix with the scalar on the diagonal and zeros everywhere else. There's no other scalar->array promotion in numpy that acts even vaguely like that. So should @ do what dot does, should it broadcast, or... what? There's no great answer, and scalar @ matrix is pointless anyway (you can just use * instead), so we punted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.