3

numpy.array(value) evaluates to true, if value is int, float or complex. The result seems to be a shapeless array (numpy.array(value).shape returns ()).

Reshaping the above like so numpy.array(value).reshape(1) works fine and numpy.array(value).reshape(1).squeeze() reverses this and again results in a shapeless array.

What is the rationale behind this behavior? Which use-cases exist for this behaviour?

5
  • You get a scalar from a scalar. What's not rational about that? Commented Jul 31, 2019 at 11:43
  • Also, the call to squeeze is missing parens Commented Jul 31, 2019 at 11:43
  • You can pass ndmin=1 if you don't want to get a scalar. Commented Jul 31, 2019 at 11:44
  • 1
    The way I understand it, a scalar is not an array. But type(np.array(11)) is numpy.ndarray. My issue is not that I do not understand what a scalar is or what an array is but that numpy gives a scalar the type array. Commented Jul 31, 2019 at 11:49
  • 2
    It's a 0D array, not shape-less, the shape is the zero-length tuple (). There is nothing illogical about it. It is also quite useful for example if you are writing a function that you want to be able to process arrays and scalars alike. Commented Jul 31, 2019 at 12:27

1 Answer 1

3

When you create a zero-dimensional array like np.array(3), you get an object that behaves as an array in 99.99% of situations. You can inspect the basic properties:

>>> x = np.array(3)
>>> x
array(3)
>>> x.ndim
0
>>> x.shape
()
>>> x[None]
array([3])
>>> type(x)
numpy.ndarray
>>> x.dtype
dtype('int32')

So far so good. The logic behind this is simple: you can process any array-like object the same way, regardless of whether is it a number, list or array, just by wrapping it in a call to np.array.

One thing to keep in mind is that when you index an array, the index tuple must have ndim or fewer elements. So you can't do:

>>> x[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: too many indices for array

Instead, you have to use a zero-sized tuple (since x[] is invalid syntax):

>>> x[()]
3

You can also use the array as a scalar instead:

>>> y = x + 3
>>> y
6
>>> type(y)
numpy.int32

Adding two scalars produces a scalar instance of the dtype, not another array. That being said, you can use y from this example in exactly the same way you would x, 99.99% of the time, since dtypes inherit from ndarray. It does not matter that 3 is a Python int, since np.add will wrap it in an array regardless. y = x + x will yield identical results.

One difference between x and y in these examples is that x is not officially considered to be a scalar:

>>> np.isscalar(x)
False
>>> np.isscalar(y)
True

The indexing issue can potentially throw a monkey wrench in your plans to index any array like-object. You can easily get around it by supplying ndmin=1 as an argument to the constructor, or using a reshape:

>>> x1 = np.array(3, ndmin=1)
>>> x1
array([3])

>>> x2 = np.array(3).reshape(-1)
>>> x2
array([3])

I generally recommend the former method, as it requires no prior knowledge of the dimensionality of the input.

FurtherRreading:

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

4 Comments

x[()] - you can always index with a ndim tuple.
@hpaulj. Thanks for the tip. I updated the language.
Thank you for this answer and the link to the further reading. This made for an educational evening.
I just stumbled upon another way to get the value of a scalar out of a numpy array with the item function: x.item(). Inspiration came from here when researching how to work with numpy.savez()

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.