Reject Invalid Input Clearly
State a function's invalid-input rule, raise ValueError for reversed thresholds, and keep that rejection distinct from a legitimate None result.
A function sometimes receives a value that violates its input contract. It should stop at the boundary where the rule is understood and explain which rule the input broke.
State the Invalid Relationship
The measurement program classifies a reading with two thresholds:
This function assumes that low does not exceed high. With low = 22 and
high = 18, the intended regions overlap. A reading of 20 is both below the
low threshold and at least the high threshold. The first branch happens to win,
but "low" is not a valid classification for that conflicting setup.
Write the invalid relationship as an ordinary Boolean condition:
The condition is precise. Equal thresholds are allowed by this contract. They leave no ordinary interval, but they do not overlap: values below the shared threshold are low, and values at or above it are high.
Q1. Identify the invalid thresholds
Which pair violates the rule low <= high?
Select one choice, then check.
HintUse the invalid condition
Substitute each pair into low > high.
SolutionReject the reversed pair
For 22 and 18, 22 > 18 is true. The pair violates the required ordering.
The equal pair does not, because 20 > 20 is false.
Raise a Useful ValueError
Python uses raise to stop the current work with a stated exception. A
ValueError fits this case: each threshold can be compared as a number, but
their relationship is invalid for the function.
The message names the rule rather than merely saying "bad input". A caller
who sees the failure knows which two values to inspect.
Place validation near the boundary that understands the rule. classify knows
how low and high divide readings, so it validates their order before using
them. Repeating that check at every branch would scatter one rule across the
function.
For a valid call, classification proceeds normally:
For classify(20, low=22, high=18), execution stops at raise. The function
does not return a classification. A later lesson will decide when a caller can
handle one expected failure; this lesson is about making the rejection clear.
| Situation | Meaning | Function response |
|---|---|---|
low <= high | thresholds satisfy the rule | classify the reading |
low > high | caller supplied conflicting thresholds | raise ValueError |
no available readings for mean | legitimate absence defined by its contract | return None |
Q2. Choose the clear rejection
The caller supplies low = 25 and high = 20. Which response preserves the
function's rule most clearly?
Select one choice, then check.
HintPreserve the caller's evidence
The response should stop before classification and identify the relationship that failed.
SolutionRaise at the function boundary
Raising ValueError makes the invalid threshold order visible. Returning
None would confuse invalid configuration with legitimate absence, while
silently swapping values would change the caller's request.
Keep Legitimate Absence Separate
Rejection is not the right response to every case that produces no number. The
mean function from the earlier chapters already defines empty or
all-unavailable input as a legitimate absence:
These checks remain correct:
An empty input does not violate this function's contract. The result None
states that no numerical mean is available. Adding assert len(readings) > 0
or raising ValueError for the empty list would contradict behavior already
promised to callers.
The choice depends on meaning:
- return a value, including
None, when it is a legitimate result defined by the function; - raise
ValueErrorwhen caller-supplied values violate a rule the function cannot work around without changing the function's meaning.
Q3. Validate without changing valid behavior
Add the threshold validation. Keep all three valid classifications unchanged.
Editable Python
Ready to run.
HintValidate before the first branch
Add if low > high: followed by a raised ValueError. Do not alter the
classification conditions.
SolutionReject only the invalid relationship
Validation belongs where the input rule is understood. Raise ValueError
when caller-supplied thresholds conflict, and use a message that names the
rule. Keep that rejection separate from a legitimate result such as
mean([]) is None. The next lesson checks rules about the program's own
intermediate state.