Booleans and Decision Pitfalls

Introduction: Using Boolean Values as Conditions

Welcome back to Making Decisions in Python! We can guard a block with if, offer an alternative with else, and line up several alternatives with elif.

Let's pause on something we have been doing without naming it. Every condition we have written so far, score >= 90, name == "Ada", or age < 18, was a comparison that produced True or False before Python decided anything. A comparison's result can also be stored in a variable and used later as a condition.

More generally, Python tests the truth value of any expression, so a condition does not have to produce a bool. In this course, we will focus on comparisons, logical expressions, and Boolean variables.

This unit has two goals. First, we will use Boolean variables directly as conditions. Second, we will untangle two structural pitfalls that catch nearly every beginner: stacked if blocks that all run, and an if accidentally nested inside another one.

Storing a Condition in a Boolean Variable

As you may recall, a comparison produces a Boolean that we can store like any other value. Let's do exactly that:

temperature = 35
is_hot = temperature > 30

Here is what happens on each line:

  • Line 1 stores the number 35 in temperature.
  • Line 2 evaluates temperature > 30, which is 35 > 30, so True; that result is stored in is_hot.

The variable is_hot now holds a plain True: no comparison remains, just the answer. Notice the name we chose. Names such as is_hot, is_ready, or has_access read like yes-or-no questions, which document what is being tested rather than leaving a reader to decode the arithmetic behind it.

Using the Boolean Variable Directly as a Condition

Since is_hot already holds a Boolean, we can hand it straight to if:

temperature = 35
is_hot = temperature > 30

# A Boolean variable can be used directly as a condition
if is_hot:
    print("Stay hydrated.")

Python looks up is_hot, finds True, and runs the indented block:

Stay hydrated.

We deliberately did not write if is_hot == True:. That version works, but it asks a redundant question: comparing True to True to get True again. if is_hot: says the same thing with less noise, and the payoff grows when a condition is long or reused: we compute it once, give it a clear name, then test that name wherever we need it.

Pitfall 1: Several Separate if Blocks Can All Run

Now to the first pitfall. Let's score a quiz with two checks written one after another:

# Two separate if blocks: both can run
points = 100
if points >= 50:
    print("You passed.")
if points >= 100:
    print("Perfect score!")

Let's trace the interpreter with points set to 100:

  • It tests 100 >= 50, which is True, so it prints You passed.
  • The first block ends. The second if is not attached to it, so Python simply continues and tests 100 >= 100, also True, and prints Perfect score!
You passed.
Perfect score!

Two if statements at the same indentation level are two independent decisions, each evaluated on its own. Depending on the data, zero, one, or both blocks may run.

Comparing With an if/elif Chain: One Decision, One Winner

Let's now ask a similar question, but as a single if/elif chain, keeping points at 100:

# Compare with an if/elif chain, where only the first true branch runs
if points >= 100:
    print("Top tier")
elif points >= 50:
    print("Mid tier")

Python tests 100 >= 100, finds True, prints Top tier, and skips the rest of the chain; the elif is never even evaluated, though 100 >= 50 would have been True too:

Top tier

Same value, different structure, different result: the stacked version printed two lines, while the chain printed one. A handy rule of thumb: use separate if blocks when the checks are unrelated facts that can all be true at once, and use a chain when the cases are alternatives and only one should win.

Reading the Full Program and Its Output

Let's put every piece together and read the file top to bottom:

temperature = 35
is_hot = temperature > 30

# A Boolean variable can be used directly as a condition
if is_hot:
    print("Stay hydrated.")

# Two separate if blocks: both can run
points = 100
if points >= 50:
    print("You passed.")
if points >= 100:
    print("Perfect score!")

# Compare with an if/elif chain, where only the first true branch runs
if points >= 100:
    print("Top tier")
elif points >= 50:
    print("Mid tier")

Four lines appear, one per block that ran:

Stay hydrated.
You passed.
Perfect score!
Top tier

Stay hydrated. comes from the Boolean-variable test, You passed. and Perfect score! come from the two independent if blocks, and Top tier comes from the chain. The blank lines and comments carry no meaning for Python, but they show us at a glance where one decision ends and the next begins.

Pitfall 2: Accidentally Nesting One if Inside Another

The second pitfall is subtler because the code still runs. Let's take our two independent checks and indent the second one by mistake:

points = 100
if points >= 50:
    print("You passed.")
    if points >= 100:          # Oops: now inside the first block!
        print("Perfect score!")

Indentation alone changed the meaning: the second if is now a statement inside the first block, so it is only tested when points >= 50 is True. With points = 100, the bug hides perfectly since both messages still appear. Now let's set points = 100 aside and try points = 30:

  • 30 >= 50 is False, so the whole outer block is skipped.
  • The inner if is never reached, so 30 >= 100 is never tested.

Nothing prints, which is correct here. But imagine if the inner condition were points >= 10: it is True, yet its message would still never appear.

Spotting and Fixing Indentation Mistakes

These bugs are quiet, so a short checklist helps us catch them. This side-by-side sketch makes the three structures easier to compare:

[Diagram comparing independent if blocks, an if/elif chain, and accidental nesting]
  1. Line up every independent if at the same column; a stray four spaces is the whole bug.
  2. Ask, "Should this check happen no matter what?" If yes, it belongs side by side; if it only makes sense once the first condition holds, nesting is correct.
  3. Test with a value that makes the outer condition False, since that is the only case where nesting and side-by-side behave differently.

Here is the repaired version, with both if keywords starting at column one again:

points = 30
if points >= 50:
    print("You passed.")
if points >= 10:               # Aligned with the first if: always tested
    print("You scored some points.")

Now the second check runs regardless of the first, so You scored some points. prints even though the passing check failed.

Conclusion and Next Steps

Let's collect the takeaways. Python tests the truth value of the expression after if or elif, so a Boolean variable such as is_hot can be tested directly with if is_hot:, no == True required. Two if statements at the same indentation level are independent decisions, and both may run. An if/elif chain is a single decision that runs at most one branch. And indentation, nothing else, decides whether an if sits inside another block or beside it.

Congratulations on mastering these decision-making tools! We can now write programs that choose among many paths using if, else, elif, comparisons, and named Boolean conditions, and we can read a block's indentation to predict exactly what will run.

Let's put it all to the test: in the practices ahead, you will name a condition and test it directly, watch two stacked if blocks both fire, fold them into a chain that picks a single winner, and rescue a program from one misplaced indent.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal