Understanding the continue Statement
The guardian pattern adds protective checks before accessing data, preventing IndexError and other crashes when input is incomplete or malformed.
A Risky List Access
Suppose a program reads a file one line at a time and splits each line into words. It wants to process lines that begin with the word From. The first word is accessed as words[0]. That access is unsafe if the line is empty or contains only whitespace, because splitting it produces an empty list. Attempting to read words[0] then causes an IndexError before the program can compare the word with From.
What do you think happens?
What should happen when a loop encounters an empty line before it tries to use words[0]?
Reveal answer
Answer: Skip the rest of the current iteration
A guard can detect that the list is empty and use continue. This moves execution directly to the next loop iteration, so words[0] is never accessed for that line.
The Guardian Path
The guardian pattern places a protective check before a risky data access. If the input fails the check, continue skips the remaining statements in the current iteration and starts the next iteration of the loop. If the check passes, execution can safely move closer to the data access. In this way, the guard stands between malformed input and an operation that could fail.
The important order is check first, access second. The guard is useful because it prevents the dangerous operation from happening at all when the required data is absent.
Filtering One Record
The loop skips empty lines. It also skips lines whose first word is not From. Only lines that pass both checks reach print(words[2]).The two guards refine the input in stages. The first guard removes lines with no words. The second removes lines that are not interesting because they do not start with From. Each continue affects only the current iteration; it does not stop the whole loop. The processing statement at the bottom is reached only by records that pass both guards.
Refining the Data Set
It is useful to view guard clauses as a refinement process. The first guard removes records that have no words. The next guard removes records that do not begin with From. The remaining records satisfy more requirements than the original input, so the processing code can make stronger assumptions about them.
| Control-flow choice | What happens to the current record | What happens to the loop |
|---|---|---|
| continue | The remaining loop body is skipped | The next iteration begins |
| Process the record | The remaining loop body runs | The loop continues after processing |
| Stop the loop | No more records are processed | The entire loop ends |
When One Guard Is Not Enough
Passing the first guard does not prove that every later list access is safe. If a line contains the word From but has only one or two words, words[2] still fails because the third element does not exist. The first guard protects words[0] from an empty list, but it does not protect every other index used later.
For every list index used in the processing logic, ask which earlier guard guarantees that the index exists. If no guard provides that guarantee, add another guard before the access. Guardian code is an ongoing way of thinking about possible failures, not a one-time fix.
Flat Guards and Compound Conditions
Several guards can remain as separate statements, with each one expressing a single condition. This keeps the loop body flat instead of placing each later check inside another if statement. Deeply nested checks can create the Pyramid of Doom, where the useful processing logic becomes increasingly indented and harder to read and maintain.
The compound condition combines the empty-list check and the prefix check. If either condition is true, continue skips the line. This is concise, but the later words[2] access still needs its own protection if a matching line might contain fewer than three words. Combining guards does not remove the need to examine every later data access.
Practice the Guarding Mindset
A loop splits each input line into words, skips lines that do not begin with From, and then accesses words[2]. Identify the condition that can still produce an IndexError after the existing checks pass. Then describe the guard that should be added before words[2] is used.
Hints
- Look at the index used by the final access.
- Ask how many elements must exist for index 2 to be valid.
- The guard should use continue so that short records do not reach the access.
Tracing Three Kinds of Input
Determine whether each record reaches the processing statement after guards for an empty list and a first word other than From.
Empty record: The first guard detects that the list has no words, so continue skips the remaining statements for this iteration.
Record beginning with To: The list is not empty, but the second guard detects that the first word is not From, so continue skips the remaining statements.
Record beginning with From: The record passes the two described guards and reaches the remaining processing code. A separate length guard is still required before words[2] if the record might have fewer than three words.
The guards successively remove empty and uninteresting records, but every later list access requires its own safety requirement.
Key Takeaways
- A guardian check protects a risky data access by testing the required condition first.
- continue skips the rest of the current loop iteration and moves to the next iteration.
- Multiple guards refine the input, removing malformed or unwanted records before processing.
- A guard for words[0] does not automatically protect a later access such as words[2].
- Separate guards keep processing logic flat, while a compound condition can combine related skip conditions.
Key Takeaways
- Use continue as a guard mechanism when the current record is malformed or uninteresting.
- Check that required list elements exist before accessing them.
- Treat each later list access as a new safety requirement.
- Use guard clauses to keep loop logic flat and readable.
- Remember that continue skips one iteration; it does not stop the entire loop.