Every element of a 6-element list scaled by constant k = 3 via a loop. The trace shows v taking each value and result growing one scaled element per iteration.

By hand

Iterate over values directly (no index needed). Multiply each element v by k and append to result. This is the map-transform pattern from python-data-basics/ch02 with a multiply formula.

naive.py
Replay: real traced execution (multi-file project)
values = [1, 2, 3, 4, 5, 6]
k = 3
result = []
for v in values:
    result.append(v * k)
print('RESULT:', result)
  1. values ← [1, 2, 3, 4, 5, 6]

    1values = [1, 2, 3, 4, 5, 6]2k = 3
    values this step[1, 2, 3, 4, 5, 6]values
  2. k ← 3

    1values = [1, 2, 3, 4, 5, 6]2k = 33result = []
    values this step3k
  3. result ← []

    2k = 33result = []4for v in values:
    values this step[]result
  4. v ← 1

    3result = []4for v in values:5    result.append(v * k)
    values this step1v
  5. result ← [3]

    4for v in values:5    result.append(v * k)6print('RESULT:', result)
    values this step[] [3]result
  6. v ← 2

    3result = []4for v in values:5    result.append(v * k)
    values this step1 2v
  7. result ← [3, 6]

    4for v in values:5    result.append(v * k)6print('RESULT:', result)
    values this step[3] [3, 6]result
  8. v ← 3

    3result = []4for v in values:5    result.append(v * k)
    values this step2 3v
  9. result ← [3, 6, 9]

    4for v in values:5    result.append(v * k)6print('RESULT:', result)
    values this step[3, 6] [3, 6, 9]result
  10. v ← 4

    3result = []4for v in values:5    result.append(v * k)
    values this step3 4v
  11. result ← [3, 6, 9, 12]

    4for v in values:5    result.append(v * k)6print('RESULT:', result)
    values this step[3, 6, 9] [3, 6, 9, 12]result
  12. v ← 5

    3result = []4for v in values:5    result.append(v * k)
    values this step4 5v
  13. result ← [3, 6, 9, 12, 15]

    4for v in values:5    result.append(v * k)6print('RESULT:', result)
    values this step[3, 6, 9, 12] [3, 6, 9, 12, 15]result
  14. v ← 6

    3result = []4for v in values:5    result.append(v * k)
    values this step5 6v
  15. result ← [3, 6, 9, 12, 15, 18]

    4for v in values:5    result.append(v * k)6print('RESULT:', result)
    values this step[3, 6, 9, 12, 15] [3, 6, 9, 12, 15, 18]result
  16. for v in values:

    3result = []4for v in values:5    result.append(v * k)
  17. stdout ← RESULT: [3, 6, 9, 12, 15, 18]

    5    result.append(v * k)6print('RESULT:', result)
    values this stepRESULT: [3, 6, 9, 12, 15, 18]stdout

With NumPy

a * k multiplies every element of the array by the scalar k. NumPy treats the scalar as if it were broadcast to match the array's shape — each element is multiplied independently in the C loop.

library.py
import numpy as np

values = [1, 2, 3, 4, 5, 6]
k = 3
a = np.array(values)
result = a * k
print('shape:', result.shape)
print('dtype:', result.dtype)
print('values:', result.tolist())
print('RESULT:', result.tolist())
shape: (6,)
dtype: int64
values: [3, 6, 9, 12, 15, 18]
RESULT: [3, 6, 9, 12, 15, 18]

Implementation notes

  • A scalar operand is broadcast to match the array's shape: a * k is equivalent to a * np.full(a.shape, k). This scalar-to-array broadcast is the simplest case of the general broadcasting rules in ch06.
  • The same pattern works for all arithmetic operators: a + k, a - k, a / k, a ** k. For in-place scaling without allocation, use a *= k.
  • Shape, dtype, and values are shown explicitly here because ndarray.__repr__ output varies with NumPy version and print options.