A 2-row × 3-column grid and a 3-element vector added together by hand. A nested loop walks each row, then each column, adding the matching vector element to the cell. The trace shows new_row building column by column before being appended to result.

By hand

Outer loop over each row in grid. Inner loop over each column index j: add row[j] to vec[j] and append to new_row. After the inner loop finishes, append new_row to result.

naive.py
Replay: real traced execution (multi-file project)
grid = [[1, 2, 3], [4, 5, 6]]
vec = [10, 20, 30]
result = []
for row in grid:
    new_row = []
    for j in range(len(vec)):
        new_row.append(row[j] + vec[j])
    result.append(new_row)
print('RESULT:', result)
  1. grid ← [[1, 2, 3], [4, 5, 6]]

    1grid = [[1, 2, 3], [4, 5, 6]]2vec = [10, 20, 30]
    values this step[[1, 2, 3], [4, 5, 6]]grid
  2. vec ← [10, 20, 30]

    1grid = [[1, 2, 3], [4, 5, 6]]2vec = [10, 20, 30]3result = []
    values this step[10, 20, 30]vec
  3. result ← []

    2vec = [10, 20, 30]3result = []4for row in grid:
    values this step[]result
  4. row ← [1, 2, 3]

    3result = []4for row in grid:5    new_row = []
    values this step[1, 2, 3]row
  5. new_row ← []

    4for row in grid:5    new_row = []6    for j in range(len(vec)):
    values this step[]new_row
  6. j ← 0

    5new_row = []6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])
    values this step0j
  7. new_row ← [11]

    6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])8result.append(new_row)
    values this step[] [11]new_row
  8. j ← 1

    5new_row = []6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])
    values this step0 1j
  9. new_row ← [11, 22]

    6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])8result.append(new_row)
    values this step[11] [11, 22]new_row
  10. j ← 2

    5new_row = []6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])
    values this step1 2j
  11. new_row ← [11, 22, 33]

    6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])8result.append(new_row)
    values this step[11, 22] [11, 22, 33]new_row
  12. for j in range(len(vec)):

    5new_row = []6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])
  13. result ← [[11, 22, 33]]

    7        new_row.append(row[j] + vec[j])8    result.append(new_row)9print('RESULT:', result)
    values this step[] [[11, 22, 33]]result
  14. row ← [4, 5, 6]

    3result = []4for row in grid:5    new_row = []
    values this step[1, 2, 3] [4, 5, 6]row
  15. new_row ← []

    4for row in grid:5    new_row = []6    for j in range(len(vec)):
    values this step[11, 22, 33] []new_row
  16. j ← 0

    5new_row = []6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])
    values this step2 0j
  17. new_row ← [14]

    6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])8result.append(new_row)
    values this step[] [14]new_row
  18. j ← 1

    5new_row = []6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])
    values this step0 1j
  19. new_row ← [14, 25]

    6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])8result.append(new_row)
    values this step[14] [14, 25]new_row
  20. j ← 2

    5new_row = []6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])
    values this step1 2j
  21. new_row ← [14, 25, 36]

    6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])8result.append(new_row)
    values this step[14, 25] [14, 25, 36]new_row
  22. for j in range(len(vec)):

    5new_row = []6for j in range(len(vec)):7    new_row.append(row[j] + vec[j])
  23. result ← [[11, 22, 33], [14, 25, 36]]

    7        new_row.append(row[j] + vec[j])8    result.append(new_row)9print('RESULT:', result)
    values this step[[11, 22, 33]] [[11, 22, 33], [14, 25, 36]]result
  24. for row in grid:

    3result = []4for row in grid:5    new_row = []
  25. stdout ← RESULT: [[11, 22, 33], [14, 25, 36]]

    8    result.append(new_row)9print('RESULT:', result)
    values this stepRESULT: [[11, 22, 33], [14, 25, 36]]stdout

With NumPy

a + v broadcasts v (shape (3,)) across both rows of a (shape (2, 3)), adding the same vector to every row in one call.

library.py
import numpy as np

grid = [[1, 2, 3], [4, 5, 6]]
vec = [10, 20, 30]
a = np.array(grid)
v = np.array(vec)
result = a + v
print('shape:', a.shape)
print('dtype:', result.dtype)
print('values:', result.tolist())
print('RESULT:', result.tolist())
shape: (2, 3)
dtype: int64
values: [[11, 22, 33], [14, 25, 36]]
RESULT: [[11, 22, 33], [14, 25, 36]]

Implementation notes

  • Broadcasting rule: NumPy aligns shapes from the right. v is (3,), a is (2, 3) — the trailing dimension matches, so v is virtually replicated along the rows axis without copying memory.
  • The result dtype is int64 because both inputs are integer arrays. If either were float64, the result would promote to float64.
  • Shape, dtype, and values are shown explicitly here because ndarray.__repr__ output varies with NumPy version and print options.