pass is a statement that does nothing. Python needs it because every block, the indented code after a line ending in a colon, must contain at least one statement. When you want a block that has no work to do yet, pass fills the gap:
def planned_report():
pass # function to be written later
class Tank:
pass # an empty class is still a valid classThis lesson shows where pass is useful, why it is not the same as continue, what a function containing only pass returns, and better alternatives for code that should not run silently, such as raising NotImplementedError. The examples come from an aquarium planning its feeding reports.
Empty blocks
Python uses indentation to define blocks, so an empty one would be indistinguishable from no block at all. Writing a colon and then nothing indented is a syntax error:
def planned_report():
^
IndentationError: expected an indented block after function definition on line 1pass is the smallest valid statement, so it's used anywhere a block is required but there's nothing to do yet: a function you'll write later, a class you'll fill in, an if branch you haven't decided on, or a loop body while you test the loop header.
A docstring also counts as a statement, so a function or class containing only a docstring is valid without pass. The ellipsis literal ... is another common placeholder, especially in type stubs and abstract method definitions; like pass, it does nothing when executed.
Function results
A function whose body is just pass runs, does nothing, and returns None, because every Python function that ends without a return statement returns None:
def feeding_count():
pass
result = feeding_count()
print(result) # None
print(result + 1) # TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'That's the danger of placeholders. The program doesn't fail where the missing code is; it fails later, in whatever code used the None, which can make the bug hard to trace. A placeholder is fine during the first minutes of writing a program. Before anything else depends on the function, replace it with real code or make it fail loudly, as shown in the last section.
Loop behavior
pass doesn't affect the flow of a loop at all. The rest of the iteration still runs:
| Statement | Effect inside a loop |
|---|---|
pass | Nothing; carries on to the next line |
continue | Skips the rest of this iteration, moves to the next item |
break | Leaves the loop completely |
for tank in ["reef", "river", "empty"]:
if tank == "empty":
pass # no effect: the print below still runs
print(tank)All three names are printed. If the goal was to skip the empty tank, the statement needed is continue. Mixing these up is one of the most common beginner bugs, because the code runs without errors and only the output is wrong.
Explicit incompleteness
When unfinished code might actually be called, prefer to fail clearly instead of silently returning None. Raising NotImplementedError stops the program at the exact line that still needs work, with a message that explains why:
def feeding_report(tank):
raise NotImplementedError("feeding_report is not written yet")The same exception is used in base classes to mark methods that subclasses must provide. The abc module enforces this even earlier with @abstractmethod, which prevents the class from being instantiated until the method exists.
Never combine pass with broad exception handling:
try:
update_feeding_log()
except Exception:
pass # every error, including typos, disappearsThis swallows every error without a trace. If an error really can be ignored, catch that specific exception and leave a comment or log message explaining why.
Independent practice and a worked check
Task: replace a feeding report placeholder with a function returning a real count. Start from def feeding_count(schedule): pass and return the number of feedings that are not marked as skipped.
def feeding_count(schedule):
"""Return how many scheduled feedings will actually happen."""
count = 0
for tank, status in schedule:
if status == "skip":
continue
count += 1
return count
schedule = [("reef", "due"), ("river", "skip"), ("lagoon", "due")]
print(feeding_count(schedule)) # 2Notice that skipping uses continue; replacing it with pass would count all three. For the worked check: does pass skip the rest of a loop iteration? No. It does nothing, so the following statements still run.
Reference and next practice
The language reference describes the pass statement and NotImplementedError. Revisit loops for break and continue, and error handling for raising exceptions. Practise with the Python exercises and Python quiz.
The pass Statement Summary
- Empty blocks: pass performs no action but supplies the statement required by an otherwise empty block.
- Function results: A function with no executed value return produces None.
- Loop behavior: pass does not skip later work in a loop iteration.
- Explicit incompleteness: NotImplementedError can expose a required behavior that has not been implemented.
The pass Statement Examples
Each example shows the code, the output it produces and what each part does.
The pass Statement in a small program
def planned_report():
pass
print(planned_report())
for tank in ["reef", "river"]:
pass
print(tank)None
reef
riverLine-by-line explanation
- Lines 1 to 2A valid function whose body does nothing.
- Line 4Calling it returns
None, whichprint()displays. - Lines 6 to 7
passhas no effect on the loop;print(tank)runs on every iteration.
pass, continue and break side by side
tanks = ["reef", "closed", "river", "drained", "lagoon"]
print("pass:")
for t in tanks:
if t == "closed":
pass
print(" ", t)
print("continue:")
for t in tanks:
if t == "closed":
continue
print(" ", t)
print("break:")
for t in tanks:
if t == "drained":
break
print(" ", t)pass:
reef
closed
river
drained
lagoon
continue:
reef
river
drained
lagoon
break:
reef
closed
riverLine-by-line explanation
- Lines 5 to 6
passchanges nothing, so "closed" is still printed. - Lines 11 to 12
continueskips only the "closed" iteration. - Lines 17 to 18
breakstops the loop before "drained", so later tanks are never visited.
Common The pass Statement Mistakes
Using pass when you meant continue
for tank in tanks:
if tank == "closed":
pass # does not skip
schedule_feeding(tank)for tank in tanks:
if tank == "closed":
continue
schedule_feeding(tank)pass is a no-op; continue is what moves to the next item.
Leaving a placeholder that returns None
def daily_portions(fish_count):
pass
total = daily_portions(12) * 3 # TypeError far from the causedef daily_portions(fish_count):
raise NotImplementedError("portion rules not decided yet")A loud failure at the placeholder is easier to fix than a TypeError somewhere else.
The pass Statement in Real Projects
Placeholders in real projects
Developers often sketch a program's structure first: function names, class names and the main loop, each with pass or ... as the body, then fill them in one at a time. Custom exception classes are often just class FeedingError(Exception): pass, because inheriting from Exception is all they need.
Linters help keep placeholders under control. Ruff and Pylint flag unnecessary pass statements and bare except: pass blocks, and many teams search for NotImplementedError and TODO before a release to make sure nothing unfinished ships.
The pass Statement FAQ
What does pass do in Python?
Nothing. It is a placeholder statement that satisfies Python's rule that every block must contain at least one statement. Execution simply moves on to the next line.
What is the difference between pass and continue?
pass does nothing and the rest of the loop body still runs. continue skips the rest of the current iteration and moves to the next item. Outside loops, continue is a SyntaxError, while pass is valid anywhere a statement is.
Should I use pass or ... as a placeholder?
Both do nothing when executed. pass is the traditional choice in normal code. ... (Ellipsis) is common in type stubs, protocols and abstract methods, where it reads as "body intentionally omitted". Pick one style per project.
Why do I get "expected an indented block"?
A line ending with a colon, such as if, for, def or class, must be followed by at least one indented statement. Add the real code, or pass as a temporary placeholder, indented under the header.
Is except: pass bad practice?
Usually, yes. It hides every error, including bugs you didn't anticipate, and leaves no record. Catch only the specific exception you expect and log or comment on why it is safe to ignore.
The pass Statement Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Does pass skip the rest of a loop iteration?
Which review concern is valid for the pass statement?
The pass Statement Quiz
2 questions to check what you learned.
Does pass skip the rest of a loop iteration?
- Yes
- No
- Python ignores the distinction
Which statement correctly describes loop behavior?
- pass does not skip later work in a loop iteration.
- Only the example output matters, not the rule
- Every operation has the same behavior