Array Creation and Data Types
NumPy provides several idiomatic ways to build arrays. You can convert existing Python sequences with np.array(), generate ranges with np.arange() or evenly spaced points with np.linspace(), or use shape-based constructors like np.zeros(), np.ones(), np.full(), and np.eye() for identity matrices. Each constructor infers a dtype automatically unless you specify one explicitly with the dtype keyword, and getting the dtype right up front avoids costly re-casting later.
Cricket analogy: Building a season's scores array with np.array() from a Python list, or generating over-by-over markers with np.arange(), infers a dtype automatically, while np.zeros() can pre-allocate an empty scorecard grid before filling in results.
Type Inference and Explicit dtypes
When you pass a list of Python ints to np.array(), NumPy infers int64 (on most 64-bit systems); a list containing any float produces float64. This automatic promotion follows a hierarchy: bool < int < float < complex, and mixing types promotes to the 'widest' compatible type. You can override inference with dtype=np.float32 for memory savings, or dtype=np.int8 for small-range integers, trading range/precision for a smaller memory footprint — valuable when arrays are large.
Cricket analogy: A list of over counts like [1, 2, 3] infers int64, but adding a strike rate like 45.5 promotes the whole array to float64; you could instead force dtype=np.int8 for jersey numbers, since they never need a huge range.
arange, linspace, and Random Arrays
np.arange(start, stop, step) behaves like Python's range() but returns an array and accepts float steps (though float steps can accumulate rounding error, so np.linspace(start, stop, num) is often preferred when you need an exact count of evenly spaced points). For randomized data, the modern API uses a Generator object: np.random.default_rng(seed) followed by .random(), .integers(), or .normal(), which is preferred over the legacy np.random.seed()-based functions for reproducibility and statistical correctness.
Cricket analogy: np.arange(1, 51, 1) behaves like counting overs 1 through 50, but float run-rate steps can accumulate rounding error, so np.linspace is better when you need exactly 20 evenly spaced power-play checkpoints; a Generator seeded with default_rng simulates a fair coin toss reproducibly.
import numpy as np
# From a Python list -- dtype inferred as int64
ints = np.array([1, 2, 3])
print(ints.dtype) # int64
# Explicit dtype for memory savings
small = np.array([1, 2, 3], dtype=np.int8)
print(small.nbytes) # 3 bytes vs 24 bytes for int64
# Shape-based constructors
zeros = np.zeros((2, 3)) # 2x3 array of 0.0
ones = np.ones((3,), dtype=int) # [1 1 1]
identity = np.eye(3) # 3x3 identity matrix
# Ranges
range_arr = np.arange(0, 10, 2) # [0 2 4 6 8]
lin_arr = np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1. ]
# Reproducible random data
rng = np.random.default_rng(seed=42)
random_arr = rng.integers(low=0, high=100, size=5)Choosing int8 instead of int64 for a column of small counts (0-127) cuts memory usage to 1/8th -- a meaningful saving when working with tens of millions of rows, which is exactly the kind of decision pandas makes internally when you call df.astype().
np.arange() with float steps can produce an unexpected number of elements due to floating-point rounding (e.g. np.arange(0, 1, 0.1) may include or exclude the endpoint inconsistently) -- prefer np.linspace() when the exact count matters.
- np.array() infers dtype from input following the hierarchy bool < int < float < complex.
- Shape-based constructors (zeros, ones, full, eye) create arrays of a given shape without listing values.
- np.arange() mirrors range() but supports float steps, which can introduce rounding artifacts.
- np.linspace() guarantees an exact number of evenly spaced points, avoiding arange's float-step pitfalls.
- Explicit dtype selection (e.g. int8 vs int64) trades numeric range for significant memory savings.
- np.random.default_rng() is the modern, recommended API for reproducible random array generation.
Practice what you learned
1. What dtype does np.array([1, 2.5, 3]) produce?
2. Why is np.linspace often preferred over np.arange when a precise number of points is needed?
3. What is the main benefit of specifying dtype=np.int8 instead of the default int64 for small integer data?
4. Which function is the modern, recommended API for generating reproducible random NumPy arrays?
5. What does np.eye(3) return?
Was this page helpful?
You May Also Like
The ndarray: NumPy Basics
The ndarray is NumPy's core data structure — understanding its shape, dtype, strides, and axis conventions is essential to using arrays correctly and efficiently.
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.
Data Type Conversion
Master how to inspect and convert pandas column dtypes with astype, to_numeric, to_datetime, and category types to fix incorrect or inefficient typing.
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.