Module 3 · Lesson 6

Case Study: Vectorizing a Real Loop

Let’s take a realistic loop-based function and vectorize it end to end.

def score_loop(values):
    """Clip each value into [0, 100], then apply a bonus:
    +10 if the clipped value is above 80, otherwise no bonus."""
    out = []
    for v in values:
        v = max(0, min(100, v))
        if v > 80:
            v += 10
        out.append(v)
    return out

A tempting shortcut is np.vectorize(score_loop_single_element): it looks vectorized because it accepts arrays, but internally it still calls your Python function once per element in a Python loop — you get NumPy’s syntax without NumPy’s speed. Prefer composing real ufuncs (np.clip, np.where, comparisons) instead.

def score_loop(values):
    out = []
    for v in values:
        v = max(0, min(100, v))
        if v > 80:
            v += 10
        out.append(v)
    return out


def score_vectorized(values):
    clipped = np.clip(values, 0, 100)
    return np.where(clipped > 80, clipped + 10, clipped)


sample = [-5, 50, 85, 120]
print(score_loop(sample))
print(score_vectorized(np.array(sample)))

Output:

[0, 50, 95, 110]
[  0  50  95 110]
6.1

Vectorize the scoring function

Write score_vectorized_checked(values) that reproduces score_loop's behavior exactly (clip to [0, 100], then +10 bonus if the clipped value is > 80) using only np.clip and np.where — no loop, no np.vectorize. Return a NumPy array.

💡 Hint

Clip first with np.clip(values, 0, 100), then use np.where on the clipped result to add the bonus conditionally.

✅ Solution
def score_vectorized_checked(values):
    clipped = np.clip(values, 0, 100)
    return np.where(clipped > 80, clipped + 10, clipped)
6.2

Spot the fake vectorization

Write is_real_ufunc_pipeline(func) that takes a function and returns False if func is an instance of np.vectorize (i.e. built by wrapping a scalar Python function), and True otherwise. This is a quick sanity check you can literally run on your own code to catch accidental fake vectorization.

💡 Hint

Use isinstance(func, np.vectorize).

✅ Solution
def is_real_ufunc_pipeline(func):
    return not isinstance(func, np.vectorize)

🎯 Key Takeaways

Next up: Module 4 — Aggregations, Statistics & Sorting, where you’ll learn to summarize and reorder array data along any axis.