VMware ESXi and vSphere Cluster Management

Python pass Statement: Placeholder Blocks and the Difference from continue

Learn how Python's pass statement works, why empty blocks need it, and how pass differs from continue and break in loops.

The Python pass statement is a null operation: when Python executes it, nothing happens. It does not assign a value, print output, change a variable, move a loop forward, or alter program flow by itself.

Its main purpose is to provide a valid statement where Python requires an indented block, even when you intentionally have no behavior to add yet.

What pass does

Python uses indentation to define a block, also called a suite. A suite is the indented group of statements belonging to constructs such as if, for, def, class, try, or with.

Every such construct needs at least one statement in its body. pass supplies that statement without performing an operation.

if True:
    pass

This code is valid. The condition is true, Python enters the indented block, executes pass, and then continues after the block.

By contrast, an empty block is not valid Python:

if True:
    # There is no statement here

Depending on the exact whitespace and surrounding code, Python reports a syntax- or indentation-related error because the if statement has no body. Add a real statement when the branch needs behavior, or add pass when the empty branch is intentional.

Basic pass syntax

pass is written on its own line inside an indented block:

if condition:
    pass

It can also be used in different conditional branches:

if status == "ready":
    print("Start")
elif status == "paused":
    pass
else:
    print("Unknown status")

Here, the paused branch deliberately has no action. The pass statement makes the branch valid, and execution continues after the entire conditional statement.

pass may appear wherever an ordinary statement is allowed. It is most useful in a block that temporarily needs no behavior or represents an intentionally empty case.

Where pass can be used

if or else branch — A branch may be recognized but require no action yet. Use pass as its body.

for or while loop — The loop body must contain a statement. Use pass when each iteration intentionally performs no operation.

function definition — A planned function can be defined before its implementation is ready.

class definition — An empty class can act as a marker or a custom exception type.

try/except handler — A narrowly selected, expected exception can be deliberately ignored.

with statement — A context-managed block still needs a body, even if no work is required inside it.

The surrounding compound statement requires a body because Python's syntax associates the indented suite with that statement. The typical placeholder purpose differs, but the role of pass is the same: satisfy the syntax without adding behavior.

pass in a conditional inside a loop

Consider a for loop over the numbers 1 through 10. Python's range(1, 11) produces 1 through 10 because the ending value, 11, is excluded.

for number in range(1, 11):
    if number == 5:
        pass
        print("The number is 5")
    print(number)

Expected output:

1
2
3
4
The number is 5
5
6
7
8
9
10

When number is 5, Python enters the if block and executes pass. It then continues to the next statement in that same block, so The number is 5 is printed. After leaving the conditional block, the loop prints 5 as well.

This demonstrates two important facts:

  • pass does not skip the remaining statements in the current if block.
  • pass does not skip the current loop iteration or move directly to the next number.

pass versus continue

continue is a loop-control statement. When Python executes it, the current iteration ends immediately, and the loop begins its next iteration.

Replacing pass with continue changes the result:

for number in range(1, 11):
    if number == 5:
        continue
        print("The number is 5")
    print(number)

In this version, when number is 5, continue skips the rest of that iteration. Therefore neither the special message nor the final print(number) runs for 5.

1
2
3
4
6
7
8
9
10

The two statements can look similar when a branch has no desired action, but they are not substitutes in general. Use pass when the branch should do nothing and then continue normally. Use continue when the rest of the current loop iteration must be skipped.

pass — Can be used outside a loop: Yes. Remaining statements in the current iteration: They run normally. Effect on the loop: None. Typical use: A no-operation placeholder for a required block.

continue — Can be used outside a loop: No. Remaining statements in the current iteration: They are skipped. Effect on the loop: Starts the next iteration. Typical use: Ignore the rest of one iteration.

break — Can be used outside a loop: No. Remaining statements in the current iteration: They are skipped because the loop ends. Effect on the loop: Exits the nearest enclosing loop. Typical use: Stop searching or processing when a condition is met.

Counting lowercase l characters in Hello world!

This example iterates over every character in the string Hello world!. The counter starts at zero. When the current character is a lowercase l, the branch contains pass before the counter update and match-specific message.

text = "Hello world!"
count = 0

for character in text:
    if character == "l":
        pass
        count += 1
        print("Found a lowercase l")
    print(character)

print("Total:", count)

Relevant output is:

H
e
l
Found a lowercase l
l
Found a lowercase l
o
 
w
o
r
l
Found a lowercase l
d
!
Total: 3

The string contains three lowercase l characters. On each match, pass does nothing and execution continues to count += 1 and the message. The character is also printed by the statement after the conditional.

If you put continue at the same location, the statements below it in the current iteration would be skipped:

for character in text:
    if character == "l":
        continue
        count += 1
        print("Found a lowercase l")
    print(character)

In this arrangement, the counter would not increase for any lowercase l, and the per-match message would never print. The character print would also be skipped for each matching iteration. To use continue correctly, required updates must occur before it, or the logic must be reorganized.

Legitimate placeholder use cases

Function stubs

A stub is a temporary definition that reserves an interface for code planned later.

def load_settings(filename):
    pass

This function can be parsed and imported, but it returns None when called because it has no return statement. A stub should not be mistaken for a finished implementation.

When callers must not use the function yet, an explicit error is often clearer:

def load_settings(filename):
    raise NotImplementedError("Settings loading is not implemented yet")

During development, add a comment or TODO when that communicates the plan:

def load_settings(filename):
    # TODO: read and validate the settings file
    pass

Marker classes and custom exceptions

A class does not need additional methods or attributes to have a useful identity. An empty class can serve as a marker:

class ExperimentalFeature:
    pass

It can also define a custom exception type:

class InvalidUserInput(Exception):
    pass

The class name now gives code a specific exception type to catch or raise, even though the class body adds no custom behavior.

Temporarily unimplemented branches

if output_format == "json":
    write_json(data)
elif output_format == "xml":
    # TODO: add XML support
    pass
else:
    raise ValueError("Unsupported output format")

This is valid while XML support is being developed. Leaving a clear TODO reduces the chance that a silent placeholder will be forgotten.

Intentionally ignored exceptions

A narrow exception handler may use pass when failure is expected and has no useful consequence:

try:
    os.remove("temporary-cache.txt")
except FileNotFoundError:
    pass

Not finding an optional temporary file may be harmless. However, catch only the specific exception you understand. A broad handler such as except Exception: pass can hide programming errors, configuration problems, and data loss.

Empty loop bodies

An empty loop body can be made syntactically valid with pass:

for item in items:
    pass

This is sometimes useful when merely consuming or waiting through an iterable is intentional, but it may be unclear to readers. A comment, a meaningful function call, or a clearer loop structure is often preferable.

pass and the ellipsis placeholder

The literal ... is called an ellipsis. It is another commonly used placeholder, especially in type stubs, protocol declarations, and incomplete APIs.

def parse_record(value: str) -> dict:
    ...

Both pass and ... can make a function body syntactically nonempty, but they communicate different intentions. pass explicitly says “perform no operation.” An ellipsis is commonly understood as “details are omitted” or “this declaration has no implementation here.” Choose the form that best communicates the code's purpose and conventions.

For production code, consider whether a real implementation, a return value, logging, or an explicit exception is more appropriate than a silent pass. Silent placeholders can make unfinished logic appear successful.

pass, continue, break, and loop else

break exits the nearest enclosing loop. continue skips to the next iteration. pass changes neither the loop nor the statements that follow it.

A loop can also have an else clause. The loop's else block runs when the loop finishes normally, without encountering break.

for number in range(1, 4):
    if number == 5:
        break
else:
    print("The loop completed without break")

Because the loop reaches its natural end, the message is printed. Replacing the condition with one that calls break would prevent the loop else block from running. A pass statement inside the loop would not affect this rule.

Choosing the right statement

  • Use pass when a required block intentionally has no operation.
  • Use continue when the rest of the current loop iteration should not run.
  • Use break when the nearest loop should end immediately.
  • Use a real implementation when the path is required for correct behavior.
  • Use raise NotImplementedError when unfinished code must fail clearly rather than silently doing nothing.
  • Use logging or an explanatory comment when ignoring an expected condition needs to be visible to maintainers.

Troubleshooting pass-related mistakes

An empty block causes an error

Cause: A compound statement has no body statement.

Fix: Add the intended code, or add pass if the block is deliberately empty.

Code after pass still runs

Cause: pass is a no-operation, not a skip instruction.

Fix: Use continue to skip the rest of a loop iteration, break to exit a loop, or restructure the conditional logic.

A counter stops updating after continue is added

Cause: continue bypasses every statement below it in that iteration.

Fix: Move required updates before continue, or use an if/else structure that separates the cases clearly.

Errors disappear without explanation

Cause: A broad exception handler silently ignores failures.

Fix: Catch only expected exception types, and log, handle, or re-raise unexpected errors.

A placeholder remains in production code

Cause: pass allows unfinished logic to run silently.

Fix: Implement the behavior, add a tracked TODO during development, or raise NotImplementedError when the path must not be used.

Key points

  • pass is a Python statement representing a null operation.
  • It is mainly used to satisfy Python's requirement that an indented block contain at least one statement.
  • It does not change variables, output, loop position, or program flow by itself.
  • Unlike continue, it does not skip later statements in a loop iteration.
  • Unlike break, it does not terminate a loop.
  • Use it deliberately, document unfinished work, and avoid hiding unexpected exceptions.

For a concise reference, return to the pass statement guide.