Understand the contract
An assertion states that an internal condition should hold if the program is correct. When the condition is false, Python raises AssertionError, optionally with a message. It is useful for catching broken assumptions close to their source during development.
Assertions are not input validation. Python can remove assert statements when running with optimization, such as python -O. Authentication, permissions, data integrity, and required argument checks must use normal conditionals and explicit exceptions.
Follow the runtime behavior
In ordinary execution the condition is evaluated first; the message expression is evaluated only if the condition fails. With assertions disabled, neither expression should be relied on to run. Never put a required mutation or function call only inside assert.
These examples assume ordinary Python execution without -O. Unit-test assertion methods such as self.assertEqual are ordinary method calls and are distinct from the removable assert statement.
Apply it and practise
Use assertions for developer-facing invariants after the program has already validated external data. Give a message that identifies the violated rule, not a duplicate of the expression.
Exercise: write a function that rejects negative input using ValueError and asserts that its computed square is non-negative. Explain which check must remain active with optimization and why.
Syntax
assert condition, "explanation of the invariant"Examples
Check an internal invariant
Use an invariant to detect an unexpected internal state during development.
values = [2, 4, 6]
total = sum(values)
assert total >= 0, "non-negative inputs must have a non-negative sum"
print(total)- sum runs before the assertion. The condition is true, so execution reaches print and the message is unused.
- Use an invariant to detect an unexpected internal state during development.
- The assertion may disappear under -O; this cannot enforce a required external data rule.
- Expected output: 12
Inspect a failed assertion
Use this failure to locate a broken counter invariant while debugging.
try:
remaining = -1
assert remaining >= 0, "remaining count became negative"
except AssertionError as error:
print(error)- The deliberately false condition raises AssertionError. The handler prints the message so the demonstration finishes without an uncaught traceback.
- Use this failure to locate a broken counter invariant while debugging.
- In optimized execution the assert may be removed and this script prints nothing; run it without -O.
- Expected output: remaining count became negative
Keep validation explicit
Use this separation when a function has both caller requirements and developer assumptions.
def square(value: int) -> int:
if value < 0:
raise ValueError("value must be non-negative")
result = value * value
assert result >= 0, "square invariant failed"
return result
try:
square(-1)
except ValueError as error:
print(error)
print(square(3))- The explicit if guards the public requirement in every execution mode. The assertion checks an internal result separately, and the valid call returns nine.
- Use this separation when a function has both caller requirements and developer assumptions.
- The example requires an integer-like input by convention; type annotations alone do not enforce that requirement.
- Expected output: value must be non-negative 9
Best practices
- These examples assume ordinary Python execution without -O. Unit-test assertion methods such as self.assertEqual are ordinary method calls and are distinct from the removable assert statement.
- Use assertions for developer-facing invariants after the program has already validated external data. Give a message that identifies the violated rule, not a duplicate of the expression.
Runtime & versions
Python interpreter. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
Python language reference