Command Palette

Search for a command to run...

Hectal
PHASE 2Beginner ~26 min· topic 2 of 9

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, both a and b are operands.
Evaluate
Work out the value of an expression.
Expression
A piece of code that produces a value, like 2 + 3 or age >= 18.
Statement
A piece of code that does something, like an if block or an assignment. It does not itself produce a value.
Conditional expression
The form a if condition else b. It produces a when the condition is true, otherwise b. 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 or is 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.

main.pywhole filepython
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.

Reading it in the right orderdiagram
Rendering diagram…

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.

main.pywhole filepython
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.

main.pywhole filepython
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.

main.pywhole filepython
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.

main.pywhole filepython
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.

main.pywhole filepython
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. 1

    Make it plural

    Write a line that prints 1 file when count = 1 and 3 files when count = 3, using a conditional expression for the letter s. Change count to 0 and check the result. ("0 files" is correct English.)

  2. 2

    Find the lost zero

    In the second example change quantity = 0 to quantity = 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. 3

    Three levels

    Extend the label line with a fourth band such as "top" for 95 and above. Notice how hard it is to read. Then rewrite it as an if/elif/else block and compare.

Code & diagrams

Choosing a value with a conditional expression New tab

Change age, temp, n and x and predict each line. Setting x to 5 shows the other side of the last check.

Sign in to run this example in your browser.

Expected output

adult
hot
7 is odd
medium
safe: no division
The or default and its trap New tab

Look at the line "qty with or". A quantity of 0 became 1. Which of the two ways is right for a shopping cart?

Sign in to run this example in your browser.

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.

main.pywhole filepython
x = 1 if True
terminal
$ python main.py
── what you'll see ──
File "main.py", line 1
x = 1 if True
^^^^^^^^^
SyntaxError: expected 'else' after 'if' expression

Myth 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). So 1 + 2 if flag else 3 means (1 + 2) if flag else 3, not 1 + (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 or in configuration (timeout = timeout or 30 turns an explicit 0 into 30). Use None as the "not given" marker and test is None.

  • ▸

    In AI code the same trap appears with model settings: temperature = temperature or 0.7 ignores a deliberate temperature=0, which is exactly the setting people choose for repeatable output.

  • ▸

    Two interview classics. First, the old condition and a or b trick is wrong whenever a is falsy (True and 0 or 5 gives 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. 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 to print or use inside an f-string. An if statement, in contrast, does something and produces no value.

  2. 2

    Only the chosen side is worked out (evaluated). In 10 / x if x != 0 else "no division", when x is 0 the division is never carried out, so there is no ZeroDivisionError (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. 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 count ifs and elses, switch to a normal if/elif/else block. The test for this feature is simple: if it fits on one line and reads aloud easily, use it; otherwise don't.

  4. 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 single print("yes" if ok else "no").

  5. 5

    A shorter way to give a default is or: display = name or "Guest" means "use name if it is truthy, otherwise "Guest"". From Topic 1.8 you know or returns one of its two sides (its operands), not just True or False. This is neat for text.

  6. 6

    The trap: or decides using truthiness, so every falsy value is replaced, including valid ones. quantity or 1 turns a real 0 into 1; price or 10 turns a free item (0) into 10. When 0, "" or an empty list is a legal value, use quantity if quantity is not None else 1 instead, which replaces only a missing value. (is not None asks: "is this something other than the special empty value None?")

Explain it without notes

01

What is the syntax of the conditional expression, and how is it different from an if statement?

02

Why can value or default produce a wrong answer, and what is the correct alternative?

03

Is 10 / x if x != 0 else 0 safe when x is 0? Why?

04

When should you not use a conditional expression?

Practice

01

Set n = 4. Print n is even or n is odd using a conditional expression inside a single print.

02

Set a = 12 and b = 9. Store the bigger of the two in biggest using a conditional expression and print Biggest: 12.

03

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.

  • ↔

    **or defaults vs explicit None checks.** or is the shortest default, but it replaces every falsy value. The is None form is longer and exact.

Done when you can

  • Done when you can write a if condition else b and 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 or default and explain what goes wrong with 0.