Topics in this subject
NumPy 3 min read Updated 4 Aug 2026

2. Creating Arrays

The functions below are the workhorses for constructing arrays. Master these; they appear constantly.

The functions below are the workhorses for constructing arrays. Master these; they appear constantly.

np.array() — from existing data#

Purpose: Build an ndarray from a list/tuple/nested sequence. Syntax: np.array(object, dtype=None, copy=True, ndmin=0)

Parameter Meaning
object List/tuple/array-like to convert
dtype Force a data type (e.g. np.float32)
copy Copy input data (default True)
ndmin Minimum number of dimensions

Return: a new ndarray.

a = np.array([1, 2, 3])                 # 1-D
b = np.array([[1, 2], [3, 4]])          # 2-D
c = np.array([1, 2, 3], dtype=np.float64)
print(a, a.dtype)
print(b, b.shape)
print(c, c.dtype)

Expected Output:

[1 2 3] int64
[[1 2]
 [3 4]] (2, 2)
[1. 2. 3.] float64

⚠️ Common Mistake: np.array(1, 2, 3) fails — it expects one sequence: np.array([1, 2, 3]).

np.arange() — evenly spaced by step#

Syntax: np.arange(start, stop, step, dtype=None)stop is exclusive.

np.arange(10)          # [0 1 2 3 4 5 6 7 8 9]
np.arange(2, 10, 2)    # [2 4 6 8]
np.arange(0, 1, 0.25)  # [0.   0.25 0.5  0.75]

⚠️ Common Mistake: With float steps, rounding can add/drop an element unexpectedly. Prefer linspace when you need an exact count.

np.linspace() — evenly spaced by count#

Syntax: np.linspace(start, stop, num=50, endpoint=True, retstep=False)stop is inclusive by default.

np.linspace(0, 1, 5)              # [0.   0.25 0.5  0.75 1.  ]
np.linspace(0, 10, 5, retstep=True)  # (array([ 0. , 2.5, 5. , 7.5, 10. ]), 2.5)

💡 Tip: arange when you know the step; linspace when you know the number of points (great for plotting axes).

np.logspace() — log-scaled points#

Syntax: np.logspace(start, stop, num=50, base=10.0) → returns base**start … base**stop.

np.logspace(0, 3, 4)   # [   1.   10.  100. 1000.]   (10^0 … 10^3)

zeros, ones, empty, full#

np.zeros((2, 3))            # 2x3 of 0.0
np.ones((2, 3), dtype=int)  # 2x3 of 1
np.empty((2, 2))            # uninitialized garbage (fast, fill it yourself)
np.full((2, 3), 7)          # 2x3 of 7

⚠️ Common Mistake: np.empty does not return zeros — it returns whatever was in memory. Never read it before writing.

💡 Tip: Use zeros_like, ones_like, full_like, empty_like to match an existing array's shape and dtype:

np.zeros_like(b)   # same shape/dtype as b, filled with 0

identity, eye, diag#

np.identity(3)        # 3x3 identity matrix
np.eye(3, k=1)        # ones on the super-diagonal (k shifts the diagonal)
np.diag([1, 2, 3])    # build diagonal matrix from a vector
np.diag(np.array([[1,2],[3,4]]))   # extract diagonal -> [1 4]
Function 1-D input 2-D input
np.diag builds a diagonal matrix extracts the diagonal
np.eye identity-like, offset diagonal via k

fromfunction() & meshgrid()#

np.fromfunction(lambda i, j: i + j, (3, 3), dtype=int)
# [[0 1 2]
#  [1 2 3]
#  [2 3 4]]

x = np.array([1, 2, 3]); y = np.array([10, 20])
X, Y = np.meshgrid(x, y)
# X = [[1 2 3]        Y = [[10 10 10]
#      [1 2 3]]            [20 20 20]]

🚀 Best Practice: meshgrid is the standard way to evaluate a function f(x, y) over a grid for contour/surface plots and vectorized 2-D computations.

copy, astype, asarray#

a = np.array([1, 2, 3])
b = a.copy()               # independent deep copy
f = a.astype(np.float64)   # NEW array with a new dtype
g = np.asarray(a)          # NO copy if already an ndarray of right dtype
Function Copies? Use when
.copy() Always You need an independent array
.astype() Always (new dtype) Convert type
np.asarray() Only if needed Cheaply ensure "this is an ndarray"

Interview Question: Difference between np.array and np.asarray? np.array copies by default (copy=True). np.asarray avoids copying when the input is already an ndarray with the requested dtype — cheaper for pass-through code.

Real-world use case: np.linspace + meshgrid to build coordinate grids for image processing filters or plotting decision boundaries in ML.