The pass statement is Python’s official “do nothing” line. You use it when the grammar demands a statement—after if, def, class, for, while, try, and so on—but you are not ready to run real logic yet, or one branch should intentionally have no effect. It is not a loop control word: it does not skip iterations like continue, exit loops like break, or leave a function like return. For control flow in loops, see Python continue and Python break statement; for functions, see Python functions.
Tested on: Python 3.13.3; kernel 6.14.0-37-generic; Ubuntu 25.04.
Python pass quick reference
Use this table as a skim map; the sections below explain each row with examples.
| Use case | Use pass? |
|---|---|
| Empty function / method placeholder | Yes |
| Empty class placeholder | Yes |
Intentionally empty if / elif / else branch |
Yes |
| Empty loop body you will implement | Sometimes (mind infinite loops) |
| Ignore a specific, safe exception | Rarely—prefer logging or handling |
| Skip rest of loop iteration | No—use continue |
| Exit loop | No—use break |
| Exit function with a value | No—use return |
| Explain code only | No—use a comment (plus a real statement if the block must exist) |
What is pass in Python?
pass is a null operation: when the interpreter runs it, nothing happens and execution moves to the next statement in the same scope. It exists because Python does not allow empty indented blocks—you would get IndentationError or “expected an indented block” if you left a suite blank. During design or refactors, pass keeps the file syntactically valid until you drop in real code.
Syntax is just the keyword pass on its own line (no parentheses, no arguments). It can appear anywhere a normal statement may appear.
if True:
passThis runs with no output; the if suite is valid because pass is a real statement.
Why do we need pass in Python?
Indented suites must contain at least one statement. That rule applies to def, class, if / elif / else, for, while, try, except, finally, with, and match arms. If you truly want “no work here yet,” pass is the minimal legal filler. A comment alone does not count—the parser ignores # lines for this rule.
A valid stub uses a real statement such as pass:
def later():
pass # TODO: real bodyIf the indented suite contains only a comment, Python raises IndentationError because there is still no statement there:
def broken():
# TODO: real bodySaving that shape to a file and running it typically ends with:
IndentationError: expected an indented block after function definition on line 2The same idea applies to class, if, loops, and try / except: every suite needs something executable (pass, return, an assignment, a call, and so on).
Use pass as a placeholder
Typical reasons to reach for pass:
- Sketch a Python function or method before you implement the body.
- Declare an empty class or a stub subclass while you design the API.
- Keep one branch of an
ifchain intentionally empty while another branch runs real code. - Mark a loop body you will fill in later (avoid infinite
while True: passbusy loops unless you know you need them). - Hold a narrow
exceptclause you plan to replace with logging or recovery.
Treat most pass as temporary: once behavior exists, delete the pass or swap it for real statements.
pass in functions, classes, conditions, loops, and exceptions
pass in functions
A function body cannot be empty. pass defines a callable that runs successfully and returns None.
def todo_later():
pass
print(todo_later())You should see None because the function does nothing and falls off the end without a return value.
pass in classes
An empty class body is also illegal without a statement. pass gives you a named type you can import or subclass later.
class Placeholder:
pass
print(Placeholder.__name__)This prints Placeholder.
pass in if statements
Sometimes only one branch should act. The other branch can be pass so the structure stays explicit.
x = 3
if x < 0:
print("negative")
elif x == 0:
pass
else:
print("positive")You should see positive because the elif x == 0 suite runs only when x is zero.
pass in for loops
pass does not skip the rest of the iteration—it is a no-op line. Code after it in the same iteration still runs.
for n in (1, 2):
if n == 1:
pass
print(n)You should see 1 then 2. For “skip the rest of this iteration,” use continue in Python for loop patterns instead.
pass in while loops
The same rule applies: pass satisfies the parser inside the loop body. Avoid while True: pass with nothing else— that spins the CPU. Prefer real work, a sleep in async polling code, or a condition that becomes false.
n = 0
while n < 2:
pass # placeholder where you will add logic
n += 1
print("n is", n)You should see n is 2 because pass does not advance the loop; your own n += 1 does.
pass in exception handling
Inside except, pass means “catch and ignore.” That is sometimes right (noisy optional dependency), but it is easy to hide bugs. Prefer logging or a narrow exception type; see Python try / except and Python logging before silencing errors.
try:
int("not a number")
except ValueError:
pass
print("after")This prints after because the exception was swallowed.
pass vs continue in Python
| Statement | Meaning |
|---|---|
pass |
Do nothing; execution continues with the next statement in the same block |
continue |
End this loop iteration immediately; jump to the loop header (loops only) |
for i in range(3):
if i == 1:
pass
print("with pass", i)
for i in range(3):
if i == 1:
continue
print("with continue", i)The first loop prints all three indices; the second skips printing when i == 1.
pass vs break vs return
| Statement | Role |
|---|---|
pass |
No-op placeholder |
continue |
Skip remainder of current loop iteration |
break |
Exit the innermost loop |
return |
Exit the current function (optionally with a value) |
pass is not interchangeable with any of these; it never changes control flow beyond “this line is a valid statement.”
def demo():
for i in range(5):
if i == 0:
pass # suite must exist; does not exit the function
if i == 2:
return i
return -1
print("return exits function:", demo())
for j in range(10):
if j == 2:
break
pass
print("break exits loop, j is", j)You should see return exits function: 2 (the function returned from inside the loop) and break exits loop, j is 2 (break stopped the loop at that value of j).
pass vs comments
pass |
Comment (# ...) |
|
|---|---|---|
| Parsed as a statement | Yes | No |
| Makes an empty block legal | Yes | No |
| Can document intent | Rarely enough alone | Yes |
| Executes logic | No | No |
Comments and pass solve different problems: comments explain; pass satisfies the grammar.
def ok_stub():
pass # TODO: replace with real implementation
print(ok_stub())This prints None and is valid. A comment without pass does not create a statement:
def not_enough():
# TODO: replace with real implementationThat form triggers the same IndentationError pattern as in Why do we need pass in Python? because the suite still has no executable line.
When should you use pass?
Use pass when a suite must exist but you deliberately have no operations yet: stub functions or methods, empty placeholder classes, an intentional no-op branch, or a very narrow except you are willing to ignore after thought. Pair stubs with a short # TODO when the omission is temporary.
When should you avoid pass?
Skip pass when another statement already expresses intent: use continue, break, or return for real control flow; use logging or re-raise when an error should not vanish; use real logic instead of leaving pass in production “because it used to compile.” If the block is not required at all, remove the branch instead of filling it with pass.
Common mistakes with pass
| Mistake | Reality |
|---|---|
Treating pass like continue |
pass does not skip the rest of the loop body; use continue. |
Treating pass like return |
pass does not exit a function; execution falls through. |
Bare # in an empty block |
Comments do not satisfy the “statement required” rule. |
except Exception: pass everywhere |
You swallow real failures; narrow the exception or log. |
Leaving pass forever |
Replace with real code or delete dead structure. |
Best practices for using pass
Use pass as a short-lived structural tool, not a permanent behavior. When you stub, add a one-line comment that names what will ship next. Prefer explicit control-flow keywords in loops, and never use pass to mask errors you should handle. Remove pass as soon as the suite has real statements (Python allows dropping pass entirely once another statement exists).
Summary
pass is Python’s no-operation statement: it keeps otherwise-empty suites legal while you design stubs or express an intentional “do nothing” branch. It does not alter loops the way continue or break does, and it does not return from a function. Comments document intent but cannot replace pass where a real statement is required. The quick reference table near the top summarizes those contrasts in one place; the sections below spell them out with runnable examples. Use pass sparingly in except blocks, replace stubs as behavior lands, and reach for the right control-flow keyword when you actually need to change how execution proceeds.
References
- The
passstatement (Python language reference)

