The ndarray

NumPy · Essentials · 10 min

Every NumPy, pandas, SciPy and scikit-learn workflow is built on ndarrays, so this is the mental model everything else rests on.

NumPy is imported by convention as import numpy as np. Its central type is the ndarray: an n-dimensional array where every element has the same type and the values sit side by side in one contiguous block of memory.

That design is what makes NumPy fast. A Python list stores pointers to separate objects scattered around the heap, each with its own type tag and reference count. An ndarray of a million float64 values is just 8 MB of raw doubles plus a small header, so compiled loops can stream through it without touching the Python interpreter.

The quickest way to make one is np.array() from a Python list (or a nested list for more dimensions). Every array carries a few attributes you will check constantly:

  • ndim: number of dimensions (axes)
  • shape: a tuple with the length along each axis, e.g. (2, 3) for 2 rows and 3 columns
  • size: total number of elements
  • dtype: the element type, such as int64 or float64

Arrays behave differently from lists in two important ways. Arithmetic is element-wise: a * 2 doubles every element instead of repeating the list. And the size is fixed: there is no append method that grows the array in place (np.append exists but builds a brand-new array every call).

Printing an array shows its values without commas; repr adds array(...). Since NumPy 2, scalars pulled out of an array print in the REPL as np.int64(5) rather than plain 5; they still behave like numbers.

Example

import numpy as np

nums = [1, 2, 3, 4]
a = np.array(nums)
print(a)            # [1 2 3 4]
print(a * 2)        # [2 4 6 8]   element-wise
print(nums * 2)     # [1, 2, 3, 4, 1, 2, 3, 4]  list repetition

m = np.array([[1.0, 2.0, 3.0],
              [4.0, 5.0, 6.0]])
print(m.ndim, m.shape, m.size)   # 2 (2, 3) 6
print(m.dtype)                   # float64
print(m.nbytes)                  # 48  (6 elements x 8 bytes)

Remember

  • Import as np; build arrays with np.array(list)
  • All elements share one dtype and live in one contiguous memory block
  • shape, ndim, size and dtype describe every array
  • Operators act element-wise, unlike lists

Watch out for

  • Growing an array with np.append in a loop: each call copies everything. Collect values in a list and convert once.

Check yourself

  1. What does `np.array([1, 2, 3]) + np.array([10, 20, 30])` produce?
  2. Why is summing a large ndarray much faster than summing a list of the same numbers?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: numpy.org/doc/stable/user/absolute_beginners.html