RizTech Academy logo
RizTech Academy
Variables and Data TypesLesson 4 of 515 min

Booleans, None, and truthiness

Two small types with outsized importance. Booleans are how every decision in every program gets made, and None is Python's way of saying "nothing here" — which is a different thing from zero or an empty string, and confusing them causes real bugs.

Booleans

There are exactly two boolean values, and the capital letters are required:

is_active = True
is_deleted = False

true and false in lowercase are a NameError. This trips up anyone arriving from JavaScript.

Booleans are usually produced by a comparison rather than typed by hand:

age = 25
print(age > 18)        # True
print(age == 25)       # True
print(age != 25)       # False

Note == against =. One asks a question, the other gives an instruction. Writing if age = 25: is a SyntaxError, which is Python protecting you — in C it would silently assign and cause a genuinely nasty bug.

Combining conditions

age = 25
has_licence = True

print(age >= 18 and has_licence)    # True
print(age < 18 or has_licence)      # True
print(not has_licence)              # False

and needs both sides true. or needs at least one. not flips it.

Python lets you chain comparisons the way mathematics does, which most languages do not:

score = 75
print(0 <= score <= 100)    # True

That reads as "score is between 0 and 100". In most languages you would write score >= 0 && score <= 100.

Short-circuiting

and and or stop as soon as the answer is known:

def expensive_check():
    print("this ran")
    return True

result = False and expensive_check()

Nothing is printed. Since the left side of and is already False, the answer is False regardless, so Python never evaluates the right side.

This is not a curiosity — it is the standard way to guard an operation:

if name and name.strip():
    print("valid name")

If name is empty, the left side is falsy and name.strip() never runs. Order the conditions so the cheap or protective one comes first.

Truthiness

Here is the part that surprises people. Python will accept any value where a boolean is expected, and it has rules for which ones count as false.

Falsy values — everything in this list behaves as False:

False
None
0
0.0
""          # empty string
[]          # empty list
{}          # empty dictionary
()          # empty tuple

Everything else is truthy. Including "0", "False", -1, and [0] — all of which are non-empty, and therefore true.

Check for yourself with bool():

print(bool(0))         # False
print(bool(""))        # False
print(bool("0"))       # True   — a non-empty string
print(bool([]))        # False
print(bool([0]))       # True   — a list with one item in it

This is why you can write:

items = []
if not items:
    print("nothing to show")

rather than if len(items) == 0:. The short form is idiomatic Python and you should write it — but only once you genuinely understand what makes a value falsy, because the same convenience causes the bug in the next section.

None

None means "no value". Not zero, not empty — absent.

middle_name = None

It appears constantly in real code: a database field nobody filled in, a search that found nothing, a function that returns nothing.

That last one catches everybody:

numbers = [3, 1, 2]
result = numbers.sort()
print(result)
None

sort() sorts the list in place and returns nothing. The list was sorted — but result is None, and the next line that uses it fails confusingly. A method that changes something in place usually returns None; a method that returns a new value usually does not change the original.

Always test None with is

value = None

print(value is None)        # correct
print(value == None)        # works, but do not

Use is. It asks "are these the same object?", which is exactly the question, and it cannot be broken by a class that defines its own ==. Linters will flag == None.

The bug this all leads to

count = 0

if count:
    print("we have a count")
else:
    print("no count")
no count

0 is falsy, so this reports "no count" even though the count is genuinely zero — a real, known value. If you meant "was a count provided at all?", 0 is a perfectly good answer and this code throws it away.

Say what you actually mean:

if count is not None:
    print(f"we have a count: {count}")

Same trap with strings:

name = ""
print(name is None)     # False — it is a string, just an empty one
print(bool(name))       # False — but it is falsy

An empty string and a missing string are different situations. A form submitted with the name box left blank gives "". A form that never had a name field gives None. Treating them the same hides the difference between "the user left it empty" and "we never asked".

The rule: when 0, "" or an empty list are legitimate values in your program, test is None explicitly. Use truthiness when you genuinely mean "empty or missing, either way".

Booleans are numbers

A small oddity that is occasionally useful:

print(True + True)              # 2
print(sum([True, False, True])) # 2

True is 1 and False is 0. Summing a list of booleans counts how many are true, which is a neat way to count matches. Do not lean on it for anything else.

Practice

  1. Predict the output of each, then check: bool(""), bool(" "), bool(0), bool("0"), bool([]), bool([[]]). The last two are the interesting ones.
  2. Set age = 20 and has_ticket = False. Write one condition that is True only when someone is 18 or over and has a ticket. Then one that is True when they are under 18 or have no ticket.
  3. Run numbers = [3, 1, 2] then print(numbers.sort()). Explain why it prints None, then print the sorted list correctly.
  4. Write code where if value: and if value is not None: give different answers. Use value = 0.
  5. Set middle_name = None and print a full name that omits the middle name when it is absent. You will need an if — next module covers them properly, but attempt it now.

Next: converting between types, and why input() will trip you up exactly once.

Stuck on this lesson?

Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.

About the internship