pass

Every def, class, if, loop and except needs an indented body. pass is a body that does nothing — execution just carries on to the next line.

Control flowPython 3 (all)Live demo
empty function
def todo():
    pass
empty class
class MyError(Exception):
    pass
empty branch
if ready:
    pass  # TODO
else:
    wait()
Use for
stub functions / classes, empty except, a branch you will fill later
Result
a statement — does nothing, has no value
Pairs with
def, class, if, except, ... (Ellipsis)
Watch out
pass is not continue: the code after it still runs

Demo

Live evaluation
Negative numbers hit the pass branch — which does nothing, so they are appended like every other number.
Try:
Inputs
numberslistcomma-separated
Code
out = []
for n in [3, -1, 4, -5]:
    if n < 0:
        pass
    out.append(n)
out
Result
[3, -1, 4, -5]

pass has no behaviour of its own, so the demo shows the one question where it matters: what happens after it. With pass, the result is always the input list unchanged — the if branch exists but does nothing. Switch to the second tab and the same input loses its negatives, because continue skips the append. That difference is the whole reason to know which one you wrote.

Syntax slots

NameTypeRequiredDescription
(none)statementnopass takes nothing. It is a complete statement and can appear anywhere a statement can.

Common patterns

Custom exception class
The class body only needs to exist; everything is inherited. A docstring works as the body too.
class ConfigError(Exception):
    pass
Stub to fill in later
Lets the module import and run while the function is unwritten. It returns None.
def export_report(data):
    pass  # TODO
Ignore one specific exception
Only for an error you really expect; contextlib.suppress says the same thing more explicitly.
import os

def remove_if_exists(path):
    try:
        os.remove(path)
    except FileNotFoundError:
        pass
Ellipsis in type stubs and protocols
By convention ... marks "body intentionally left out" in .pyi stubs and abstract / Protocol methods.
from typing import Protocol

class Closer(Protocol):
    def close(self) -> None: ...

Examples

1. A stub function returns None
def todo(): pass print(todo())
Returns
None
2. An empty class
class Empty: pass Empty.__name__
Returns
'Empty'
3. Execution carries on after pass
for n in [1, 2]: pass print('after pass', n)
Returns
after pass 1 after pass 2
4. A body with nothing in it is an error
compile('def f():\n', '<demo>', 'exec')
Returns
IndentationError: expected an indented block after function definition on line 1
5. A comment is not a statement
compile('if True:\n # later\n', '<demo>', 'exec')
Returns
IndentationError: expected an indented block after 'if' statement on line 1
6. ... is the Ellipsis object
... is Ellipsis
Returns
True
7. ... works as a body too
def later(): ... print(later())
Returns
None
8. pass is not an expression
compile('x = pass', '<demo>', 'exec')
Returns
SyntaxError: invalid syntax

Pitfalls

1. pass where continue was meant
pass does not skip anything — the rest of the loop body still runs for that item.
pass
words = ['ok', '', 'fine']
out = []
for w in words:
    if not w:
        pass
    out.append(w.upper())
out
['OK', '', 'FINE']
continue
words = ['ok', '', 'fine']
out = []
for w in words:
    if not w:
        continue
    out.append(w.upper())
out
['OK', 'FINE']
2. except Exception: pass hides real bugs
Swallowing everything also swallows typos and wrong types. Catch only the exception you expect — then the real bug (an int passed in) surfaces instead of turning into None.
swallow everything
def parse(s):
    try:
        return int(s.strip())
    except Exception:
        pass
print(parse(42))
None
catch what you expect
def parse(s):
    try:
        return int(s.strip())
    except ValueError:
        return None
parse(42)
AttributeError: 'int' object has no attribute 'strip'
3. A forgotten pass stub that silently returns None
The program runs, but the stub returns None and the failure shows up far away. raise NotImplementedError fails at the call instead.
pass stub
def tax(amount):
    pass
total = 100 + (tax(100) or 0)
total
100
loud stub
def tax(amount):
    raise NotImplementedError('tax')
tax(100)
NotImplementedError: tax

When to use

Use it
  • Stub functions, classes and branches while sketching code
  • Exception subclasses that need no body
  • Ignoring one specific, expected exception
Reach for something else
  • Skipping the rest of a loop pass → continue
  • Placeholders that must not be forgotten → raise NotImplementedError
  • Silencing broad exceptions → handle or log them

Notes

CPython impl
pass does no work: at most it compiles to a NOP that keeps its line visible to line tracing (debuggers, coverage)
Ellipsis
... is an expression (the Ellipsis constant) used as a statement; as a body it behaves like pass. Convention: pass in real code, ... in stubs and protocols
Docstring
A docstring alone is a valid body, so a documented function or class needs no pass

FAQ

Nothing. It is a statement you write where the syntax requires one — an empty function, class, if branch, loop or except block — so the code parses. Execution continues with the next line.