Vectorized expressions are typically 10-100x faster than loops and read like the maths they implement.
Vectorization means expressing a computation on whole arrays instead of looping over elements. + - * / // % ** and comparisons all work element-wise between arrays of the same shape, or between an array and a scalar.
total = price * qty # instead of a loop over indexesThe work then happens in a tight C loop over typed memory. For a million elements a Python for loop takes on the order of a hundred milliseconds; the vectorized version takes about a millisecond.
A few semantics to know:
/always gives floats;//is floor division,%the matching remainder.- Division by zero on floats does not raise; it produces
infornanand emits aRuntimeWarning. Integer division by zero gives 0 with a warning. - Comparisons return boolean arrays:
a > 3is[False, True, ...], not a single bool. - Use
&,|,~to combine boolean arrays, with parentheses:(a > 1) & (a < 5). The keywordsand/ortry to turn a whole array into one bool and raiseValueError.
Operations return new arrays. To avoid allocating, use augmented assignment (a += 1), which writes in place, or the out= argument of a ufunc. In-place operations keep the array's dtype, so int_array += 0.5 raises a casting error rather than silently truncating.
Shapes must match (or be broadcast-compatible, a rule you will meet soon). Adding shape (3,) to shape (4,) raises ValueError: operands could not be broadcast together.
Example
import numpy as np
price = np.array([9.99, 4.50, 12.00])
qty = np.array([3, 10, 1])
print(price * qty) # [29.97 45. 12. ]
print((price * qty).sum()) # 86.97
a = np.arange(6)
print(a ** 2) # [ 0 1 4 9 16 25]
print(a / 2) # [0. 0.5 1. 1.5 2. 2.5]
print(a // 4, a % 4) # [0 0 0 0 1 1] [0 1 2 3 0 1]
print((a > 1) & (a < 4)) # [False False True True False False]
with np.errstate(divide="ignore"):
print(np.array([1.0, -1.0]) / 0) # [ inf -inf]
a += 10 # in place, no new array
print(a) # [10 11 12 13 14 15]Remember
- Write whole-array expressions instead of element loops
- Comparisons give boolean arrays; combine them with
&,|,~and parentheses - Float division by zero yields inf/nan with a warning, not an exception
+=and friends update in place and keep the dtype
Watch out for
- Using
and/orwith arrays, which raises 'truth value of an array is ambiguous'.