Array Operations

Math operators behave completely differently on NumPy arrays than they do on plain Python lists — and NumPy's "broadcasting" rules let you combine arrays of different (but compatible) shapes without writing a loop.

Element-wise math, not list concatenation

This is the single most important difference between a list and an array. + on two lists concatenates them; + on two arrays adds them element by element:

>>> the same operator, two different meanings
list_a = [1, 2, 3]
array_a = np.array([1, 2, 3])

print(list_a + list_a)
print(array_a + array_a)
Output
[1, 2, 3, 1, 2, 3]
[2 4 6]

list_a + list_a glues the two lists together into a longer one. array_a + array_a adds matching positions together instead — this element-wise behavior applies to -, *, /, and ** as well.

Broadcasting: combining different shapes

NumPy will automatically "stretch" a smaller array to match a larger one when their shapes are compatible — a single number is the simplest case, applied to every element:

>>> broadcasting a scalar and a row
matrix = np.array([[1, 2, 3], [4, 5, 6]])
print(matrix + 10)
print(matrix * np.array([1, 0, 1]))
Output
[[11 12 13]
 [14 15 16]]
[[1 0 3]
 [4 0 6]]

matrix + 10 broadcasts the single number 10 across every element. matrix * np.array([1, 0, 1]) broadcasts the 3-element array across each row of the matrix, since each row also has 3 columns — effectively zeroing out the middle column.

Note: broadcasting only works when shapes are compatible — matching exactly, or one of them being 1 in a given dimension. Multiplying a (2, 3) matrix by a 2-element array raises a ValueError: operands could not be broadcast together. When broadcasting fails, check that the trailing dimensions of both shapes actually line up.