Multiply two length-4 vectors element by element and accumulate the sum. The trace shows total growing after each pairwise multiplication, making the sum-of-products definition concrete before the single-call NumPy version.

By hand

Loop over each index i, multiply a[i] by b[i], and add the product to total. The result is a single number — the scalar dot product.

naive.py
Replay: real traced execution (multi-file project)
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
total = 0
for i in range(len(a)):
    total += a[i] * b[i]
print('RESULT:', total)
  1. a ← [1, 2, 3, 4]

    1a = [1, 2, 3, 4]2b = [5, 6, 7, 8]
    values this step[1, 2, 3, 4]a
  2. b ← [5, 6, 7, 8]

    1a = [1, 2, 3, 4]2b = [5, 6, 7, 8]3total = 0
    values this step[5, 6, 7, 8]b
  3. total ← 0

    2b = [5, 6, 7, 8]3total = 04for i in range(len(a)):
    values this step0total
  4. i ← 0

    3total = 04for i in range(len(a)):5    total += a[i] * b[i]
    values this step0i
  5. total ← 5

    4for i in range(len(a)):5    total += a[i] * b[i]6print('RESULT:', total)
    values this step0 5total
  6. i ← 1

    3total = 04for i in range(len(a)):5    total += a[i] * b[i]
    values this step0 1i
  7. total ← 17

    4for i in range(len(a)):5    total += a[i] * b[i]6print('RESULT:', total)
    values this step5 17total
  8. i ← 2

    3total = 04for i in range(len(a)):5    total += a[i] * b[i]
    values this step1 2i
  9. total ← 38

    4for i in range(len(a)):5    total += a[i] * b[i]6print('RESULT:', total)
    values this step17 38total
  10. i ← 3

    3total = 04for i in range(len(a)):5    total += a[i] * b[i]
    values this step2 3i
  11. total ← 70

    4for i in range(len(a)):5    total += a[i] * b[i]6print('RESULT:', total)
    values this step38 70total
  12. for i in range(len(a)):

    3total = 04for i in range(len(a)):5    total += a[i] * b[i]
  13. stdout ← RESULT: 70

    5    total += a[i] * b[i]6print('RESULT:', total)
    values this stepRESULT: 70stdout

With NumPy

np.dot(va, vb) computes the dot product in one call. The equivalent operator va @ vb does the same for 1-D inputs. The snapshot shows both input shapes and dtypes, then the scalar result.

library.py
import numpy as np

a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
va = np.array(a)
vb = np.array(b)
result = int(np.dot(va, vb))
print('a: shape:', va.shape, 'dtype:', va.dtype, 'values:', va.tolist())
print('b: shape:', vb.shape, 'dtype:', vb.dtype, 'values:', vb.tolist())
print('dot product:', result)
print('RESULT:', result)
a: shape: (4,) dtype: int64 values: [1, 2, 3, 4]
b: shape: (4,) dtype: int64 values: [5, 6, 7, 8]
dot product: 70
RESULT: 70

Implementation notes

  • The dot product sums pairwise products and returns a scalar, collapsing two length-n vectors to a single number. Contrast with elementwise-product (ch03), which multiplies position by position and returns an array of the same length — no summation occurs there.
  • For 1-D arrays np.dot(a, b) and a @ b are identical. For 2-D arrays @ is matrix multiplication; np.dot has subtly different broadcasting rules. Prefer @ for matrix work; use np.dot only for 1-D dot products.
  • Both inputs must have the same length; mismatched shapes raise a ValueError.
  • Shape, dtype, and values are shown explicitly here because ndarray.__repr__ output varies with NumPy version and print options.