and

Both must hold — but the result is an operand, and the right side may never run.

Logical operatorPython 1.0+Live demo
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
aaLeft operand — its truthiness decides whether b runs at all.type: Any · required and bbRight 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

NameTypeRequiredDescription
aAnyyesLeft operand — its truthiness decides whether b runs at all.
bAnyyesRight operand — evaluated (and returned) only when a is truthy.

Return value

Anya 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
False

Pitfalls

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.