Replace each element that fails a condition with a fixed value. A loop uses a ternary expression to keep each value if it is non-negative, substituting 0 otherwise. The trace shows result accumulating one element per iteration, with negative values silently replaced.

By hand

Loop over values. For each v, append v if v >= 0 else append 0. Python's conditional expression (x if cond else y) evaluates to x when cond is True and y when False.

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

    1values = [3, -1, 5, -2, 0, 4]2result = []
    values this step[3, -1, 5, -2, 0, 4]values
  2. result ← []

    1values = [3, -1, 5, -2, 0, 4]2result = []3for v in values:
    values this step[]result
  3. v ← 3

    2result = []3for v in values:4    result.append(v if v >= 0 else 0)
    values this step3v
  4. result ← [3]

    3for v in values:4    result.append(v if v >= 0 else 0)5print('RESULT:', result)
    values this step[] [3]result
  5. v ← -1

    2result = []3for v in values:4    result.append(v if v >= 0 else 0)
    values this step3 -1v
  6. result ← [3, 0]

    3for v in values:4    result.append(v if v >= 0 else 0)5print('RESULT:', result)
    values this step[3] [3, 0]result
  7. v ← 5

    2result = []3for v in values:4    result.append(v if v >= 0 else 0)
    values this step-1 5v
  8. result ← [3, 0, 5]

    3for v in values:4    result.append(v if v >= 0 else 0)5print('RESULT:', result)
    values this step[3, 0] [3, 0, 5]result
  9. v ← -2

    2result = []3for v in values:4    result.append(v if v >= 0 else 0)
    values this step5 -2v
  10. result ← [3, 0, 5, 0]

    3for v in values:4    result.append(v if v >= 0 else 0)5print('RESULT:', result)
    values this step[3, 0, 5] [3, 0, 5, 0]result
  11. v ← 0

    2result = []3for v in values:4    result.append(v if v >= 0 else 0)
    values this step-2 0v
  12. result ← [3, 0, 5, 0, 0]

    3for v in values:4    result.append(v if v >= 0 else 0)5print('RESULT:', result)
    values this step[3, 0, 5, 0] [3, 0, 5, 0, 0]result
  13. v ← 4

    2result = []3for v in values:4    result.append(v if v >= 0 else 0)
    values this step0 4v
  14. result ← [3, 0, 5, 0, 0, 4]

    3for v in values:4    result.append(v if v >= 0 else 0)5print('RESULT:', result)
    values this step[3, 0, 5, 0, 0] [3, 0, 5, 0, 0, 4]result
  15. for v in values:

    2result = []3for v in values:4    result.append(v if v >= 0 else 0)
  16. stdout ← RESULT: [3, 0, 5, 0, 0, 4]

    4    result.append(v if v >= 0 else 0)5print('RESULT:', result)
    values this stepRESULT: [3, 0, 5, 0, 0, 4]stdout

With NumPy

np.where(a >= 0, a, 0) applies the same logic elementwise: where the condition is True it takes the corresponding element of a, where False it uses 0. No explicit loop is needed.

library.py
import numpy as np

values = [3, -1, 5, -2, 0, 4]
a = np.array(values)
result = np.where(a >= 0, a, 0)
print('shape:', result.shape)
print('dtype:', result.dtype)
print('values:', result.tolist())
print('RESULT:', result.tolist())
shape: (6,)
dtype: int64
values: [3, 0, 5, 0, 0, 4]
RESULT: [3, 0, 5, 0, 0, 4]

Implementation notes

  • np.where(cond, x, y) is the vectorized ternary. x and y can be scalars or arrays of the same shape as cond — all three are broadcast together.
  • This pattern is commonly used for clamping: replace values below a floor (np.where(a < lo, lo, a)) or above a ceiling, or to zero out negatives before a log transform.
  • np.where always evaluates both x and y before selecting — there is no short-circuit. Side effects in x or y run regardless of the condition.
  • For the equivalent pure-Python pattern see map-transform in the python-data-basics book.
  • Shape, dtype, and values are shown explicitly here because ndarray.__repr__ output varies with NumPy version and print options.