
On Tue, Dec 28, 2021 at 10:19 AM Chris Angelico <rosuav@gmail.com> wrote:
I'm not sure about that.
numpy.log(2.71828) 0.999999327347282 numpy.log([2.71828]) array([0.99999933]) type(numpy.log(2.71828)) <class 'numpy.float64'> type(numpy.log([2.71828])) <class 'numpy.ndarray'>
well, yes, there is a odd wart in numpy that there are zero-dimensional arrays, and there are scalars, which almost, but not quite the same: In [81]: arr = np.array(3.0) In [82]: arr.shape Out[82]: () In [83]: scalar = np.float64(3.0) In [84]: scalar.shape Out[84]: () In [85]: len(arr) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-85-23f199ad2330> in <module> ----> 1 len(arr) TypeError: len() of unsized object In [86]: len(scalar) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-86-d68a51ddf681> in <module> ----> 1 len(scalar) TypeError: object of type 'numpy.float64' has no len() In [87]: 5.0 * arr Out[87]: 15.0 In [88]: 5.0 * scalar Out[88]: 15.0 But they are almost interchangeable -- the reason the distinction is there at all is for some internal numpy structural / legacy reasons. I think it boils down to numpy scalars being more-or-less interchangable with the built in python number types (https://numpy.org/neps/nep-0027-zero-rank-arrarys.html) Note that if you index into an ndarray, you get one less dimension, until you get to zero dimensions, which is a scalar. In [98]: arr2 = np.ones((3,4)) In [99]: arr2.shape Out[99]: (3, 4) In [100]: arr1 = arr2[0] In [101]: arr1.shape Out[101]: (4,) In [102]: arr0 = arr1[0] In [103]: arr0.shape Out[103]: () In [104]: arr0[0] --------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-104-29631edfe735> in <module> ----> 1 arr0[0] IndexError: invalid index to scalar variable. Anyway, the point is that the distinction between scalar and array is the same as between 1D array and 2D array, and that individual functions and operators don't need to be different for operating on different dimensions of arrays. Not sure how significant that is, but it does still distinguish between
values and arrays.
While numpy is strictly making a distinction between the *type* of scalar values and arrays, it isn't making a distinction in the *concept* of a scalar value. In the context of this thread, I think the relevant point is that "array-oriented" operations are another syntactical way of expressing operations on collections of data, as opposed to various ways to spell loopsing, which is what map() and comprehensions are. -CHB -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython