Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python comparison chains: the middle operand is evaluated once

Last updated: 30 Sept 20264 min read
tutorial
BeginnerBy AITrove Editorial

A chained comparison evaluates adjacent relations in order and stops when one relation is false.

Download Python source kit

Operation contract

The receipt amount is read through a function that records each call. The expression zero less than amount less than or equal to a cap calls that function once. The explicit and expression also calls it once here because its second comparison uses a saved local value. Repeating a function call on both sides of and would read mutable state twice and could compare two different observations.

Failure and ownership boundary

Comparison chains do not freeze the object returned by the middle expression; mutation inside a custom comparison method can still change its state. An input validator should reject bool explicitly when integer amounts are required, since bool inherits int. Python numeric operators: division, floor division and remainder contracts and Python positional-only and keyword-only parameters: keep call roles explicit cover adjacent rules.

Working program

python
reads = []
def read_amount():
    reads.append("ledger")
    return 125

print(0 < read_amount() <= 500)
print("reads:", len(reads))
amount = read_amount()
print(0 < amount and amount <= 100)
print("reads:", len(reads))

Output

Output
True
reads: 1
False
reads: 2

Costs and limits

The comparisons themselves are bounded for small integers. Calling an expensive or stateful middle expression once matters more than syntax length. Custom ordering methods and unbounded integers have their own cost.

Common Mistakes

  • Do not translate a chain into two calls to a stateful getter.
  • A chained comparison is not a transaction over mutable operands.

Connected lessons

Python numeric operators: division, floor division and remainder contracts, Python rich comparison: return NotImplemented for unsupported operands, Python positional-only and keyword-only parameters: keep call roles explicit.

python
comparison-chains
Storage details