Check an Internal Assumption

State an invariant as a relationship at one program point, assert a strong condition where it can first break, and keep internal checks separate from input validation.

Validation checks a program boundary. Inside the program, we instead ask whether its intermediate state still obeys a required relationship.

Name the Relationship That Must Hold

Suppose a loop counts every reading it examines and every available reading it processes:

Every processed reading has already been examined. Therefore this relationship must be true immediately after processed changes:

processed <= examined

An invariant is a relationship that should be true at a stated point in a program. The loop's meaning requires this one after every processed update.

Reading visitedexaminedprocessedprocessed <= examined
1811True
None21True
2132True
2043True

Q1. Choose the required invariant

Which condition expresses the relationship that every processed reading must already have been examined?

Choose one

Select one choice, then check.

HintAccount for skipped readings

A None value increases examined without increasing processed.

SolutionProcessed is bounded by examined

processed <= examined allows the two counts to be equal or processed to be smaller. It rejects the impossible state in which more readings were processed than examined.

Not attempted
Review

Not marked done.

Reuse Assert with a Useful Message

Chapter 4 used assert to compare a function result with an independently reasoned expectation. The same statement can check an internal invariant:

assert processed <= examined, "processed count cannot exceed examined count"

If the condition is false, Python raises AssertionError and shows the message. Naming both counts preserves more evidence than "something went wrong".

Place the assertion immediately after the update that could first break the rule:

This placement keeps the first bad state beside the code that created it.

Q2. Place the check where the state changes

A loop increments processed in one statement. Where should the invariant processed <= examined be checked?

Choose one

Select one choice, then check.

HintStop at the first bad state

Ask which statement changes the left side of the invariant.

SolutionCheck after the processed update

Place the assertion immediately after processed = processed + 1. If that update creates an impossible count, the failure appears before unrelated work can obscure it.

Not attempted
Review

Not marked done.

Use a Condition Strong Enough to Catch the Defect

An assertion helps only when its condition excludes the unwanted state. This check is true in many broken runs:

assert processed >= 0

It says nothing about whether processed has moved ahead of examined. processed <= len(readings) can also miss that local defect.

The stronger local condition is:

assert processed <= examined, "processed count cannot exceed examined count"

“Stronger” here does not mean more complicated. It means that the condition rejects the particular unwanted state while remaining true for valid states.

Q3. Repair and guard the running counts

The loop incorrectly adds two processed readings for each available input. Repair the update and add the invariant immediately afterward. The final report should show four examined readings and three processed readings.

Editable Python

Command/Ctrl + Enter. Python runs in your browser.

Ready to run.

HintRepair before checking

Change the increment from two to one. On the next line, assert processed <= examined and include the stated message.

SolutionKeep the update and invariant together
Not attempted
Review

Not marked done.

Do Not Use Assertions for External Validation

Assertions check rules the program's own logic believes. Python can run with assertions disabled, so essential external validation must not depend on them.

The threshold rule from the previous lesson therefore remains ordinary validation:

Do not replace it with:

assert low <= high

The function must reject reversed caller thresholds consistently. In contrast, processed > examined means the loop has contradicted its own design.

The earlier mean contract also remains unchanged. Empty or all-unavailable readings return None. An assertion that readings must be non-empty would not check an internal invariant; it would erase a legitimate input case.

An invariant names a relationship that must hold at a particular point in the program. Check it with a strong assertion immediately after the update that could break it, and include a message that preserves local evidence. Keep assertions for internal defects; external invalid input still needs ordinary validation and a reliable rejection policy.

Pause and reflect

In your own words, note what you understood, what remains unclear, or what you want to revisit. The note stays with this lesson.

0 of 3 exercises marked done

Review

Not marked done.