Chapter 08

True and False — learning to ask questions

Comparison operators, and / or / not, chained comparisons, and which values Python treats as false — the groundwork for writing conditions.

30 minPython 3.12
  1. 1Encounter
  2. 2Understand
  3. 3Worked
  4. 4Predict
  5. 5Apply
  6. 6Stretch

The problem we are solving

A program has to decide something: does this order qualify for a discount? Is the password long enough? Is the item in stock?

The code that decides comes in the next mission (if). But before that you need the thing a decision rests on — a question whose answer is yes or no. In Python those answers are called True and False, and the type is called bool.

Today we only learn to ask, not to decide. Splitting it that way is deliberate: nearly every mistake people make writing an if is really a mistake in the question, not in the if.

By the end of this mission you can

  • Use the six comparison operators
  • Tell = and == apart
  • Join small questions into larger ones with and, or and not
  • Write chained comparisons like 18 <= age <= 60
  • Say which values Python treats as false without being False

Prerequisites: Taking input from the person using your program.


The six comparisons

python
age = 22

print(age == 22)
print(age != 22)
print(age > 18)
print(age < 18)
print(age >= 22)
print(age <= 21)
text
True
False
True
False
True
False

Every comparison produces a value — True or False. Which means a comparison can be stored in a variable:

python
age = 22
is_adult = age >= 18
print(is_adult)
print(type(is_adult))
text
True
<class 'bool'>

Naming it that way makes the code far easier to read — is_adult says what is being checked, while age >= 18 makes the reader work it out.

= and == — one character, a different meaning

python
total = 100          # an instruction: put 100 into total
print(total == 100)  # a question: is total 100?
text
True
  • = stores (assignment)
  • == asks (comparison)

Write = where a condition belongs and Python 3 raises a clear error, with a helpful message:

text
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

Good news — this mistake does not stay quiet, it gets caught.

Comparing text

python
print("rafi" == "rafi")
print("Rafi" == "rafi")
print("apple" < "banana")
print(len("password123") >= 8)
text
True
False
True
True

Two things to notice:

Case matters. "Rafi" is not equal to "rafi". When matching text a person typed, run .lower() first — otherwise anyone who capitalised their name is excluded:

python
typed = "  RAFI "
print(typed == "rafi")
print(typed.strip().lower() == "rafi")
text
False
True

< works on text too, following dictionary order — hence "apple" < "banana". That is the basis of sorting a list of names.

and, or, not

Three words join small questions into bigger ones:

python
age = 22
has_id = True

print(age >= 18 and has_id)
print(age >= 60 or has_id)
print(not has_id)
text
True
True
False
  • and — true when both are true
  • or — true when at least one is true
  • not — flips it

The whole picture at once:

python
print(True and True)
print(True and False)
print(False and False)
print(True or False)
print(False or False)
text
True
False
False
True
False
or means "one or more", not "exactly one". In everyday speech "tea or coffee?" implies one of them. Python's or is True even when both sides are true. Forget that and conditions will surprise you.

not always applies to whatever comes immediately after it, and it runs first. The order is: not first, then and, and or last.

python
print(True or False and False)
print((True or False) and False)
text
True
False

On the first line and ran first, so Python read True or (False and False) — that is True or False, which is True. On the second, the parentheses changed the order. When in doubt, use parentheses — as true here as it was for arithmetic.

Chained comparisons

To check whether something sits between two bounds, Python lets you write it the way mathematics does:

python
marks = 72

print(0 <= marks <= 100)
print(marks > 60 and marks < 80)
print(60 < marks < 80)
text
True
True
True

The second and third lines say the same thing, and the third reads better. Many languages do not allow this; Python does, and you should use it.

Which values Python treats as false

It is not only False — a handful of ordinary values count as false too:

python
print(bool(0))
print(bool(1))
print(bool(-5))
print(bool(""))
print(bool("hello"))
print(bool("0"))
print(bool("False"))
text
False
True
True
False
True
True
True

The rule in one line: zero and empty things are false, everything else is true. So 0 is false and empty text "" is false; but -5 is true (it is not zero), and "0" and "False" are true — because they are not empty, they contain characters.

Those last two lines are the real trap. Everything from input() is text, so even when someone types 0, you hold "0" — which Python considers true. To compare numbers you must convert with int() first.

The "empty is false" rule has a practical use as well — catching someone who pressed Enter without typing:

python
name = input("Name: ").strip()
print("Name was given:", bool(name))
text
Name: 
Name was given: False

A complete example

eligibility.py:

python
# Check a discount rule without deciding anything yet
age = int(input("Age            : "))
years_member = int(input("Years a member : "))
order_total = float(input("Order total    : "))

is_adult = age >= 18
is_senior = age >= 60
is_loyal = years_member >= 2
is_large_order = order_total >= 1000

# The rule: adults who are either long-standing members or spending a lot
gets_discount = is_adult and (is_loyal or is_large_order)

print()
print(f"Adult          : {is_adult}")
print(f"Senior         : {is_senior}")
print(f"Loyal member   : {is_loyal}")
print(f"Large order    : {is_large_order}")
print(f"Gets discount  : {gets_discount}")
text
Age            : 34
Years a member : 1
Order total    : 1500

Adult          : True
Senior         : False
Loyal member   : False
Large order    : True
Gets discount  : True

Notice that each condition was given its own name first, and the rule was then assembled from them. Written as one line — age >= 18 and (years_member >= 2 or order_total >= 1000) — the code would run identically, but reading it six months later to recover the rule would be hard work. The parentheses matter too: without them and would run first and the rule itself would change.


When it breaks

SyntaxError: invalid syntax. Maybe you meant '==' ... A = was written where a comparison belongs. Use ==.

These should be equal, but I get False Check three things: stray spaces (.strip()), letter case (.lower()), and type — "22" == 22 is always False, because text and a number are never equal.

TypeError: '<' not supported between instances of 'str' and 'int' You compared text with a number, probably having forgotten to convert an input(). Wrap it in int().

Two decimals will not compare equal with == Expected — recall the decimal trap from the arithmetic mission. Compare after round().

The condition does not do what it says Check and/or order: not first, then and, then or. Use parentheses to state your intent explicitly.