Topic 2.2
The One-Line if (Conditional Expression)
In one line
The conditional expression a if condition else b picks one of two values in a single line. It is perfect for choosing a value, and the or default trick is shorter still but fails when a valid value is falsy, such as 0.
Think of it like this
A sign on a shop door that says "Open" or "Closed". The sign is not a plan with steps. It is one word chosen by a yes-or-no fact ("is it before 6 pm?"). When all you need is to choose a value, the one-line form is the sign, and the full if statement of Topic 2.1 is the whole plan.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Operand
- One of the values an operator works on. In
a or b, bothaandbare operands. - Evaluate
- Work out the value of an expression.
- Expression
- A piece of code that produces a value, like
2 + 3orage >= 18. - Statement
- A piece of code that does something, like an
ifblock or an assignment. It does not itself produce a value. - Conditional expression
- The form
a if condition else b. It producesawhen the condition is true, otherwiseb. Also called the ternary operator. - Ternary
- Means "made of three parts" (value, condition, other value). Other languages write it
condition ? a : b. - Default value
- The value you use when nothing better was given.
- Short-circuit
- Stopping early: the right side of
oris not looked at when the left side is already truthy. - Sentinel (missing marker)
- A special value, usually
None, that means "nothing was provided".
Step by step
01Choosing a value in one line
Compare the long form and the short form. They do exactly the same thing. The long form is a statement that sets status in each branch. The short form is one expression that produces the value.
age = 20
# Long form
if age >= 18:
status = "adult"
else:
status = "minor"
# One-line form
status = "adult" if age >= 18 else "minor"
print(status)02Reading it in the right order
Read the one-line form as: "condition first; if true the value is the left part, otherwise the right part". Python evaluates the condition first, then only the side it needs.
03Inside other expressions
Because it is an expression, it can sit inside a print, an f-string (text with {} holes, Topic 1.9) or the brackets of a call such as print(...). This is where it shines: no extra variable and no four-line block.
n = 7
print(n, "is", "even" if n % 2 == 0 else "odd")
items = 1
print(f"{items} item{'s' if items != 1 else ''}")04Only one side runs
The side that is not chosen is never evaluated. That makes the one-line form a safe guard, for example against dividing by zero.
x = 0
result = 10 / x if x != 0 else "no division"
print("safe:", result)05Chaining, and where to stop
Two levels still read well. Three or more do not: switch to if/elif/else.
score = 82
label = "high" if score >= 90 else "medium" if score >= 60 else "low"
print(label)06The or default
name or "Guest" returns name when it is truthy, and "Guest" otherwise. An empty text is falsy, so an empty name becomes the default. This is correct here: an empty name is not a real name.
name = ""
display = name or "Guest"
print("display:", display)07The or trap with 0
For numbers, 0 is falsy, so quantity or 1 silently replaces a legal zero. The program runs and prints a wrong answer, which is the hardest kind of bug to see.
The fix is to ask the exact question: "is the value missing?" (is not None). Then 0 is kept.
quantity = 0
wrong = quantity or 1
right = quantity if quantity is not None else 1
print(wrong) # 1 (0 was thrown away)
print(right) # 0 (0 is kept)08What or and and really return
or returns the first truthy operand, or the last operand if none is truthy. and returns the first falsy operand, or the last operand if all are truthy. This is why 0 or [] or "x" is "x", and "" and "b" is '' (the empty text).
Try it yourself
- 1
Make it plural
Write a line that prints
1 filewhencount = 1and3 fileswhencount = 3, using a conditional expression for the letters. Change count to 0 and check the result. ("0 files" is correct English.) - 2
Find the lost zero
In the second example change
quantity = 0toquantity = 5. The wrong version now works by luck. A bug that only shows for one special value is why it is worth knowing the trap. - 3
Three levels
Extend the
labelline with a fourth band such as"top"for 95 and above. Notice how hard it is to read. Then rewrite it as anif/elif/elseblock and compare.
Code & diagrams
Change age, temp, n and x and predict each line. Setting x to 5 shows the other side of the last check.
Expected output
adult
hot
7 is odd
medium
safe: no divisionLook at the line "qty with or". A quantity of 0 became 1. Which of the two ways is right for a shopping cart?
Expected output
display: Guest
qty with or: 1
qty with None check: 0
missing: 1
x
b
''Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Leave out the else
Write the one-line form with no else part.
x = 1 if TrueMyth vs fact
Myth
The one-line if is always better because it is shorter.
Fact
It is better only when it reads easily. Nested or long versions are harder to read than a plain block. Shorter code is not the goal; clearer code is.
Myth
x or default is the same as x if x is not None else default.
Fact
They differ for every falsy value: 0, "", [], False. or replaces all of them, while the is not None form replaces only None.
Myth
Both sides of the one-line if are evaluated.
Fact
Only the chosen side runs. The other side can even contain an error that never happens, such as a division by zero.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The conditional expression has very low precedence (it is worked out after almost every other operator), just above
lambda(a tiny one-line function, Phase 5). So1 + 2 if flag else 3means(1 + 2) if flag else 3, not1 + (2 if flag else 3). Add brackets when you mix it with other operators. - ▸
A related trick from old Python,
(b, a)[condition], evaluates both values and indexes a tuple. Don't use it: it evaluates both sides and hides the intent. The conditional expression replaced it in Python 2.5. - ▸
In production code, default handling is a common source of bugs with
orin configuration (timeout = timeout or 30turns an explicit0into 30). UseNoneas the "not given" marker and testis None. - ▸
In AI code the same trap appears with model settings:
temperature = temperature or 0.7ignores a deliberatetemperature=0, which is exactly the setting people choose for repeatable output. - ▸
Two interview classics. First, the old
condition and a or btrick is wrong wheneverais falsy (True and 0 or 5gives 5), which is why the conditional expression was added (PEP 308). Second, do not confuse the two comprehension forms:[a if c else b for x in xs]keeps every item and chooses a value, while[a for x in xs if c]drops items (Topic 4.7).
Remember this
- 1
The form is
value_if_true if condition else value_if_false. It reads almost like English:status = "adult" if age >= 18 else "minor". It is an expression, so it gives a value that you can store in a variable, pass toprintor use inside an f-string. Anifstatement, in contrast, does something and produces no value. - 2
Only the chosen side is worked out (evaluated). In
10 / x if x != 0 else "no division", whenxis 0 the division is never carried out, so there is noZeroDivisionError(the crash you get from dividing by zero). The order looks unusual: the condition sits in the middle of the text, but Python works it out first. - 3
You can chain them:
"high" if s >= 90 else "medium" if s >= 60 else "low". It works, but two levels is the practical limit. If the reader has to countifs andelses, switch to a normalif/elif/elseblock. The test for this feature is simple: if it fits on one line and reads aloud easily, use it; otherwise don't. - 4
Do not use the one-line form for actions.
print("yes") if ok else print("no")runs, but it uses an expression to do a statement's job and hides intent. Write the normal block, or put the choice inside a singleprint("yes" if ok else "no"). - 5
A shorter way to give a default is
or:display = name or "Guest"means "usenameif it is truthy, otherwise"Guest"". From Topic 1.8 you knoworreturns one of its two sides (its operands), not just True or False. This is neat for text. - 6
The trap:
ordecides using truthiness, so every falsy value is replaced, including valid ones.quantity or 1turns a real0into1;price or 10turns a free item (0) into 10. When0,""or an empty list is a legal value, usequantity if quantity is not None else 1instead, which replaces only a missing value. (is not Noneasks: "is this something other than the special empty valueNone?")
Explain it without notes
What is the syntax of the conditional expression, and how is it different from an if statement?
Why can value or default produce a wrong answer, and what is the correct alternative?
Is 10 / x if x != 0 else 0 safe when x is 0? Why?
When should you not use a conditional expression?
Practice
Set n = 4. Print n is even or n is odd using a conditional expression inside a single print.
Set a = 12 and b = 9. Store the bigger of the two in biggest using a conditional expression and print Biggest: 12.
Set nickname = "" and name = "Ravi". Store nickname if it is not empty, otherwise name, in shown, using or, and print it.
Trade-offs
- ↔
Brevity vs clarity. One line is quick to write and read when the choice is simple. Longer chains trade clarity away for no real gain.
- ↔
**
ordefaults vs explicit None checks.**oris the shortest default, but it replaces every falsy value. Theis Noneform is longer and exact.
Done when you can
Done when you can write
a if condition else band say which part runs first.Done when you can explain why only one side is evaluated.
Done when you can name the limit for chaining and rewrite a long chain as a block.
Done when you can show the
ordefault and explain what goes wrong with0.