The ndarray: NumPy Basics
Every NumPy array is an instance of the ndarray class, characterized by a handful of core attributes: shape (the size along each dimension), dtype (the element type), ndim (the number of dimensions), and size (total element count). These attributes are not just metadata for inspection — they directly determine how operations behave, how memory is laid out, and how broadcasting rules apply. A solid mental model of shape and axes is the single most valuable skill for working confidently with NumPy and, later, pandas.
Cricket analogy: A cricket scoreboard has a shape (overs, players), a dtype like int for runs, an ndim of 2, and a total size equal to overs times players - these attributes dictate how you'd sum runs per over versus per player, just like ndarray attributes govern operations.
Shape, Axes, and Dimensions
A 1-D array has shape (n,) and a single axis, axis 0. A 2-D array has shape (rows, cols): axis 0 runs down the rows, axis 1 runs across the columns. When you call a reduction like array.sum(axis=0), you are collapsing along axis 0 — summing down each column — which often trips up beginners who expect it to sum across rows. Higher-dimensional arrays (3-D, 4-D) extend this pattern, common in image batches (batch, height, width, channels) or time-series tensors.
Cricket analogy: A single batsman's over-by-over score is shape (n,) on axis 0, but a full team's scorecard is shape (players, overs): axis 0 runs down players, axis 1 across overs, so array.sum(axis=0) sums down each over-column across all players, not across one player's overs.
dtype and Memory Layout
The dtype attribute (e.g. int64, float32, bool) determines how many bytes each element occupies and how those bytes are interpreted. NumPy arrays are, by default, stored in row-major ('C') order, meaning the last axis varies fastest in memory; this affects cache performance for large arrays and is worth knowing when transposing or reshaping. The itemsize attribute tells you bytes-per-element, and nbytes gives the total memory footprint (size * itemsize).
Cricket analogy: Whether you store a batsman's runs as int8 or int64 changes bytes per entry, much like a scorecard's row-major layout (batsman by batsman) means reading one player's whole innings is faster than pulling one over across all players.
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float64)
print(arr.shape) # (2, 3) -- 2 rows, 3 columns
print(arr.ndim) # 2
print(arr.dtype) # float64
print(arr.size) # 6 total elements
print(arr.itemsize) # 8 bytes per element
print(arr.nbytes) # 48 bytes total
# Axis-aware reduction
print(arr.sum(axis=0)) # [5. 7. 9.] -- sums DOWN each column
print(arr.sum(axis=1)) # [ 6. 15.] -- sums ACROSS each rowA helpful trick: axis=0 always means 'collapse this dimension,' so summing over axis=0 in a 2-D array removes the row dimension, leaving one value per column — the opposite of what many newcomers guess.
Reshaping (e.g. arr.reshape(3, 2)) usually returns a view sharing the same underlying data buffer, not a copy — mutating the reshaped array can silently mutate the original.
- shape, ndim, dtype, and size are the core attributes that define an ndarray's structure.
- Axis 0 refers to rows (moving down); axis 1 refers to columns (moving across) in a 2-D array.
- Reduction operations collapse along the specified axis, removing that dimension from the result.
- NumPy arrays default to row-major (C-order) memory layout, affecting performance and reshape behavior.
- itemsize and nbytes let you reason precisely about an array's memory footprint.
- Reshape and similar operations often return views, not copies, so mutations can propagate unexpectedly.
Practice what you learned
1. For a 2-D array, what does arr.sum(axis=0) compute?
2. What does the .shape attribute of a NumPy array return?
3. What is the default memory layout order for a newly created NumPy array?
4. Why might mutating a reshaped array unexpectedly change the original array?
5. If a float64 array has size 10, how many bytes does it occupy (ignoring overhead)?
Was this page helpful?
You May Also Like
What Is NumPy?
NumPy is Python's foundational library for fast, memory-efficient numerical computing, built around a homogeneous multi-dimensional array type called ndarray.
Array Creation and Data Types
NumPy offers many ways to construct arrays — from literals to specialized constructors — and choosing the right dtype affects both correctness and memory efficiency.
Array Indexing and Slicing
NumPy supports basic slicing, fancy (array) indexing, and boolean masking, each with distinct rules about whether the result is a view or a copy.
Array Reshaping and Stacking
Reshaping changes an array's shape without altering its data, while stacking and splitting functions combine or divide arrays along chosen axes.