and
Both must hold — but the result is an operand, and the right side may never run.
Common call
if user and user.active:
Returns
first falsy operand, else the last operand
Replaces
"" and "x" is '' — not False
Watch out
short-circuit: b is skipped entirely when a is falsy
aa — Left operand — its truthiness decides whether b runs at all.type: Any · required and bb — Right operand — evaluated (and returned) only when a is truthy.type: Any · required
→ Any
Demo
Live evaluation
Try:
Inputs
aAnyempty = falsy
bAnyright operand
Output
'x' and 'y'
'y'
Watch the outputs: they are OPERANDS, not True/False. Truthy a → you get b; falsy a (the empty string here) → you get a back. Inside an if this behaves like boolean AND, because the result is then truth-tested.
Operands
| Name | Type | Required | Description |
|---|---|---|---|
| a | Any | yes | Left operand — its truthiness decides whether b runs at all. |
| b | Any | yes | Right operand — evaluated (and returned) only when a is truthy. |
Return value
Any — a when a is falsy, otherwise b — an OPERAND, not necessarily a bool. b is never evaluated when a is falsy (short-circuit).
Common patterns
Guarded attribute access
The left side protects the right from raising.
if user and user.is_admin: ...
Guarded computation
Short-circuit as control flow.
total and total_errors / total # 0 when total is 0
Examples
1. Both truthy → last operand
"x" and "y"
Returns
'y'2. Falsy left → left returned
"" and "y"
Returns
''3. In a condition
bool(1 and 0)
Returns
FalsePitfalls
1. The result is not a bool
Code storing `a and b` gets an operand — fine for truth tests, surprising elsewhere.
Operand leaks
flag = name and True print(flag)
'' when name is empty — not False
Force bool
flag = bool(name)
True/False
2. Side effects on the right may never run
Short-circuiting skips b entirely.
Skipped call
ok and log_attempt()
log_attempt never called when ok is falsy
Explicit
if ok: log_attempt()
intent visible
3. and is not &
& is bitwise (and non-short-circuiting) — different operator entirely.
Wrong tool
a() & b() # both always run
no short-circuit, bitwise semantics
Fix
a() and b()
short-circuits
When to use
Use it
- Combined conditions in if/while
- Guard-then-use chains (null-safe access)
Reach for something else
- Element-wise boolean ops on arrays → & (numpy/pandas)
- Storing a guaranteed bool → wrap in bool()
- Default-if-falsy values → that is or’s job
Notes
Complexity
O(1) plus operand evaluation
Return
an operand — a if falsy, else b
CPython impl
Compiled to JUMP_IF_FALSE_OR_POP — not a dunder method
Memory
No allocation
Thread-safe
Depends only on the operand expressions
FAQ
It enables guard idioms: `user and user.name` gives you the name or the falsy user directly. Truth-testing contexts coerce it anyway, so nothing is lost.
History
1.0
Core operator from the beginning.