A stepped numeric sequence built manually with a while-loop, then generated in one call. The trace steps through x advancing by step each iteration and seq growing until x reaches stop.

By hand

Initialise x = start, then loop while x < stop: append x to seq, then advance x by step. This is exactly the rule np.arange follows — stop is exclusive, and the sequence ends at the last value strictly below it.

naive.py
Replay: real traced execution (multi-file project)
start = 1.0
stop = 4.0
step = 0.5
seq = []
x = start
while x < stop:
    seq.append(x)
    x += step
print('RESULT:', seq)
  1. start ← 1.0

    1start = 1.02stop = 4.0
    values this step1.0start
  2. stop ← 4.0

    1start = 1.02stop = 4.03step = 0.5
    values this step4.0stop
  3. step ← 0.5

    2stop = 4.03step = 0.54seq = []
    values this step0.5step
  4. seq ← []

    3step = 0.54seq = []5x = start
    values this step[]seq
  5. x ← 1.0

    4seq = []5x = start6while x < stop:
    values this step1.0x
  6. while x < stop:

    5x = start6while x < stop:7    seq.append(x)
  7. seq ← [1.0]

    6while x < stop:7    seq.append(x)8    x += step
    values this step[] [1.0]seq
  8. x ← 1.5

    7    seq.append(x)8    x += step9print('RESULT:', seq)
    values this step1.0 1.5x
  9. while x < stop:

    5x = start6while x < stop:7    seq.append(x)
  10. seq ← [1.0, 1.5]

    6while x < stop:7    seq.append(x)8    x += step
    values this step[1.0] [1.0, 1.5]seq
  11. x ← 2.0

    7    seq.append(x)8    x += step9print('RESULT:', seq)
    values this step1.5 2.0x
  12. while x < stop:

    5x = start6while x < stop:7    seq.append(x)
  13. seq ← [1.0, 1.5, 2.0]

    6while x < stop:7    seq.append(x)8    x += step
    values this step[1.0, 1.5] [1.0, 1.5, 2.0]seq
  14. x ← 2.5

    7    seq.append(x)8    x += step9print('RESULT:', seq)
    values this step2.0 2.5x
  15. while x < stop:

    5x = start6while x < stop:7    seq.append(x)
  16. seq ← [1.0, 1.5, 2.0, 2.5]

    6while x < stop:7    seq.append(x)8    x += step
    values this step[1.0, 1.5, 2.0] [1.0, 1.5, 2.0, 2.5]seq
  17. x ← 3.0

    7    seq.append(x)8    x += step9print('RESULT:', seq)
    values this step2.5 3.0x
  18. while x < stop:

    5x = start6while x < stop:7    seq.append(x)
  19. seq ← [1.0, 1.5, 2.0, 2.5, 3.0]

    6while x < stop:7    seq.append(x)8    x += step
    values this step[1.0, 1.5, 2.0, 2.5] [1.0, 1.5, 2.0, 2.5, 3.0]seq
  20. x ← 3.5

    7    seq.append(x)8    x += step9print('RESULT:', seq)
    values this step3.0 3.5x
  21. while x < stop:

    5x = start6while x < stop:7    seq.append(x)
  22. seq ← [1.0, 1.5, 2.0, 2.5, 3.0, 3.5]

    6while x < stop:7    seq.append(x)8    x += step
    values this step[1.0, 1.5, 2.0, 2.5, 3.0] [1.0, 1.5, 2.0, 2.5, 3.0, 3.5]seq
  23. x ← 4.0

    7    seq.append(x)8    x += step9print('RESULT:', seq)
    values this step3.5 4.0x
  24. while x < stop:

    5x = start6while x < stop:7    seq.append(x)
  25. stdout ← RESULT: [1.0, 1.5, 2.0, 2.5, 3.0, 3.5]

    8    x += step9print('RESULT:', seq)
    values this stepRESULT: [1.0, 1.5, 2.0, 2.5, 3.0, 3.5]stdout

With NumPy

np.arange(start, stop, step) generates the same sequence in one call. The snapshot shows the array's shape, dtype, and values, then adds a linspace(1, 4, 7) values line to contrast: linspace includes the stop value and accepts a point count rather than a step size.

library.py
import numpy as np

start, stop, step = 1.0, 4.0, 0.5
arr = np.arange(start, stop, step)
ls = np.linspace(1, 4, 7)
print('shape:', arr.shape)
print('dtype:', arr.dtype)
print('values:', [round(v, 10) for v in arr.tolist()])
print('linspace(1, 4, 7) values:', ls.tolist())
print('RESULT:', [round(v, 10) for v in arr.tolist()])
shape: (6,)
dtype: float64
values: [1.0, 1.5, 2.0, 2.5, 3.0, 3.5]
linspace(1, 4, 7) values: [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]
RESULT: [1.0, 1.5, 2.0, 2.5, 3.0, 3.5]

Implementation notes

  • np.arange follows the same start-inclusive, stop-exclusive rule as Python's range. With a float step, floating-point rounding can occasionally produce an extra element or drop the last one — np.linspace avoids this by computing positions as start + i * (stop - start) / (n - 1).
  • Choose arange when the step size is the natural parameter (sensor sampling interval, grid resolution). Choose linspace when the number of points is the natural parameter (plotting 100 points over an interval).
  • The while-loop in the "By hand" half is the same accumulation pattern as running-total in python-data-basics/ch02, but accumulates positions rather than a cumulative sum.
  • Shape, dtype, and values are shown explicitly here because ndarray.__repr__ output varies with NumPy version and print options.