Build a combined boolean mask from two conditions (lower and upper bound) and use it to filter a list. The first loop produces the mask with and; the second loop applies it with if m. The trace shows combined growing one boolean at a time, then filtered collecting only the values that pass both conditions.

By hand

First loop: for each v append v > lo and v < hi to combined — Python's and short-circuits if the first condition is False. Second loop: zip the values and mask together; append the value only when m is True.

naive.py
Replay: real traced execution (multi-file project)
values = [1, 5, 3, 8, 4, 9]
lo = 2
hi = 6
combined = []
for v in values:
    combined.append(v > lo and v < hi)
filtered = []
for v, m in zip(values, combined):
    if m:
        filtered.append(v)
print('RESULT:', (combined, filtered))
  1. values ← [1, 5, 3, 8, 4, 9]

    1values = [1, 5, 3, 8, 4, 9]2lo = 2
    values this step[1, 5, 3, 8, 4, 9]values
  2. lo ← 2

    1values = [1, 5, 3, 8, 4, 9]2lo = 23hi = 6
    values this step2lo
  3. hi ← 6

    2lo = 23hi = 64combined = []
    values this step6hi
  4. combined ← []

    3hi = 64combined = []5for v in values:
    values this step[]combined
  5. v ← 1, combined ← [False]

    pass 1 of 6
    4combined = []5for v in values:6    combined.append(v > lo and v < hi)7filtered = []
    values this step1v[] [False]combined
    All 6 passes — pass 1 is the card above
    passvcombined
    11[] [False]
    21 5[False] [False, True]
    35 3[False, True] [False, True, True]
    43 8[False, True, True] [False, True, True, False]
    58 4[False, True, True, False] [False, True, True, False, True]
    64 9[False, True, True, False, True] [False, True, True, False, True, False]
  6. for v in values:

    4combined = []5for v in values:6    combined.append(v > lo and v < hi)
  7. filtered ← []

    6    combined.append(v > lo and v < hi)7filtered = []8for v, m in zip(values, combined):
    values this step[]filtered
  8. v ← 1, m ← False

    pass 1 of 2
    7filtered = []8for v, m in zip(values, combined):9    if m:10        filtered.append(v)
    values this step9 1vFalsem
  9. m ← True, v ← 5

    pass 2 of 2
    7filtered = []8for v, m in zip(values, combined):9    if m:10        filtered.append(v)
    values this stepFalse Truem1 5v
  10. filtered ← [5], v ← 3

    pass 1 of 2
    7filtered = []8for v, m in zip(values, combined):9    if m:10        filtered.append(v)11print('RESULT:', (combined, filtered))
    values this step[] [5]filtered5 3v
  11. filtered ← [5, 3], m ← False, v ← 8

    pass 2 of 2
    7filtered = []8for v, m in zip(values, combined):9    if m:10        filtered.append(v)11print('RESULT:', (combined, filtered))
    values this step[5] [5, 3]filteredTrue Falsem3 8v
  12. m ← True, v ← 4

    7filtered = []8for v, m in zip(values, combined):9    if m:
    values this stepFalse Truem8 4v
  13. if m:

    8for v, m in zip(values, combined):9    if m:10        filtered.append(v)
  14. filtered ← [5, 3, 4]

    9    if m:10        filtered.append(v)11print('RESULT:', (combined, filtered))
    values this step[5, 3] [5, 3, 4]filtered
  15. m ← False, v ← 9

    7filtered = []8for v, m in zip(values, combined):9    if m:
    values this stepTrue Falsem4 9v
  16. if m:

    8for v, m in zip(values, combined):9    if m:10        filtered.append(v)
  17. for v, m in zip(values, combined):

    7filtered = []8for v, m in zip(values, combined):9    if m:
  18. stdout ← RESULT: ([False, True, True, False, True, False], [5, 3, 4])

    10        filtered.append(v)11print('RESULT:', (combined, filtered))
    values this stepRESULT: ([False, True, True, False, True, False], [5, 3, 4])stdout

With NumPy

(a > lo) & (a < hi) applies both comparisons elementwise and combines them with bitwise AND. The result is a boolean array, passed directly to a[mask] for boolean indexing.

library.py
import numpy as np

values = [1, 5, 3, 8, 4, 9]
lo, hi = 2, 6
a = np.array(values)
mask = (a > lo) & (a < hi)
filtered = a[mask]
print('mask: shape:', mask.shape, 'dtype:', mask.dtype, 'values:', mask.tolist())
print('filtered: shape:', filtered.shape, 'dtype:', filtered.dtype, 'values:', filtered.tolist())
print('RESULT:', (mask.tolist(), filtered.tolist()))
mask: shape: (6,) dtype: bool values: [False, True, True, False, True, False]
filtered: shape: (3,) dtype: int64 values: [5, 3, 4]
RESULT: ([False, True, True, False, True, False], [5, 3, 4])

Implementation notes

  • Use & (bitwise AND) and | (bitwise OR) on NumPy boolean arrays, not Python's and/or. Python's and/or operate on the truthiness of the whole array (raising an error for ambiguous multi-element arrays).
  • Parentheses are required: (a > lo) & (a < hi). Without them, & binds tighter than > and <, so a > lo & a < hi is parsed as a > (lo & a) < hi — a comparison chain, not two masked conditions.
  • The combined mask (a > lo) & (a < hi) is equivalent to a[a > k] from filter-with-mask generalized to a range.
  • Shape, dtype, and values are shown explicitly here because ndarray.__repr__ output varies with NumPy version and print options.