Embercode
✕
ConditionalsLesson 13 of 14

35 min read

None checks before conditions in Python

Why this matters

Many conditions use a value in a function or a method. A condition like len(name) > 0 asks Python for the length of name and compares the answer with zero. That works when name holds text. It stops the program with an error when name holds nothing at all.

In Python, the word for "nothing" is None. Passing None to len, or calling a method on it, stops the program. Python reports this with an error such as TypeError or AttributeError, and the error message names NoneType, which is the type of None.

This lesson covers the habit that prevents that error. You check for None first, in the same condition, before you use the value. You also learn why the order of the checks matters when you combine them with and and or. The if statement itself is covered in the earlier lessons of this module, and this lesson does not repeat them.

To run the examples, save each one in a file, then run it with python3 file_name.py in a terminal. The examples were run with Python 3.14.4. The error messages in this lesson show the file name only, without the folder path in front of it.

What None means

A name such as name points to a value. None is a special value that means "no value". You assign it on purpose. A function that ends without a return line gives back None too.

Think of a name tag with nothing written on it. You can look at the tag and see that it is empty. You cannot read a name from it. Asking the tag for its length gives no answer. None is the empty tag.

A method is a function that belongs to a value. The text "Ada " has a method called strip, written "Ada ".strip(), which returns the text with spaces removed from both ends. A method call on None fails, because None has no methods of that kind.

Python has exactly one None. To test whether a value is None, write is None or is not None. The word is asks whether two names point to the same object, and since there is only one None, this is the correct test. The test does not use the value itself, so it is always safe to ask:

Python · editable
True
False

Do not confuse None with zero or with an empty string. Zero is a number, and an empty string is text with no characters in it. Both are real values that len and the other operations can work with. None means there is no value at all, so there is nothing to measure or call a method on.

A crash in one line

Here is the smallest program that fails. The name name is None, and the condition passes it to len.

name = None
if len(name) > 0:
    print("has a name")
print("after")
Traceback (most recent call last):
  File "null_crash.py", line 2, in <module>
    if len(name) > 0:
       ~~~^^^^^^
TypeError: object of type 'NoneType' has no len()

A traceback is the report Python prints when an error stops the program. The last line holds the error type and the message. The message says that len received a NoneType value, which is None. The line numbers point to the place where the program stopped, which is line 2. The line print("after") never runs. The marks under the code, such as ~~~^^^^^^, show the part of the line that failed.

The fix is to ask the is not None question before the call, in the same condition:

Python · editable
no name

The condition now has two steps. First, name is not None asks whether there is a value to measure. Second, len(name) > 0 measures it. The and between them means the second step runs only if the first one is true. That detail is the subject of the next section.

Order matters with and

The word and means that both parts must be true. Python evaluates the left side first. If the left side is False, the result of the whole and is already known to be False, so Python skips the right side. This is called short-circuit evaluation, which means Python stops as soon as the answer is known. A null check on the left protects the call on the right.

Here is a loop over four values. One of them is None, one is an empty string, and two are real names. The condition puts the None check first.

Python · editable
ok: Ada
skipped: None
skipped: 
ok: Grace

For the None value, the left side name is not None is False, so Python never calls len. The program prints skipped: None. The empty string is not None, so the left side is True, and the right side measures it. The length is zero, so the test fails and the program prints skipped: followed by nothing. An empty string and None are different things. An empty string is a value with no characters. None has no value at all.

Now the same condition with the two parts swapped:

name = None
if len(name) > 0 and name is not None:
    print("never printed")
Traceback (most recent call last):
  File "null_order.py", line 2, in <module>
    if len(name) > 0 and name is not None:
       ~~~^^^^^^
TypeError: object of type 'NoneType' has no len()

The left side is evaluated first, so len(name) runs before the None check. The check on the right never gets a chance to protect anything. The rule is simple: the None check goes on the left of and.

Order matters with or

The word or means that at least one part must be true. Python evaluates the left side first. If the left side is True, the whole or is True, and Python skips the right side. The None check still goes on the left, because the right side must not run when the value is None.

A common test is "the text is missing or it is blank." A blank string has only spaces, or no characters at all. The method strip removes spaces at both ends, so a blank string becomes an empty string after strip.

Python · editable
text: Ada
blank: None
blank: 

When s is None, the left side s is None is True, so Python stops there and never calls strip. When s holds text, the left side is False, and Python calls strip. Reversing the two parts gives the crash:

inputs = ["Ada", None, ""]
for s in inputs:
    if s.strip() == "" or s is None:
        print("blank:", s)
    else:
        print("text:", s)
text: Ada
Traceback (most recent call last):
  File "null_or.py", line 3, in <module>
    if s.strip() == "" or s is None:
       ^^^^^^^
AttributeError: 'NoneType' object has no attribute 'strip'

The first value printed correctly. The second value is None, so s.strip() fails before the None check is reached. The error is an AttributeError, which means the object does not have the attribute, here the method strip.

Truthiness and the short form if name

Python treats some values as false when they are used in a condition. This is called truthiness. None, zero, an empty string, and an empty list are all false. Most other values are true. Because of this, if name: is true only when name holds a value with something in it, and it catches None and the empty string in one step.

Python · editable
None False
'' False
0 False
[] False
'Ada' True

The function repr shows a value the way Python writes it in code, so the empty string appears as ''. The function bool converts a value to True or False in the same way a condition does.

The short form is convenient, but it also treats 0 as missing. If a count of zero is a valid answer, if count: gives the wrong result for it. Use is not None when you need to tell None apart from the other false values.

The next example uses or to give a default value when the first one is missing. It also shows where the short form goes wrong:

Python · editable
none
Ada

The empty string is false, so or gives the second value, "none". That is the result you want for a missing value. It is also the result for an empty string, which may not be what you want. For the difference, use is not None.

Chained checks

Sometimes the value you check sits inside another value. A user has an address, and the address has a city. Any of these steps can be None. An expression such as user.address.city fails at the first None in the chain. The fix is one check for each step, in order, before the next step uses the value.

A class is a blueprint for objects that hold related values. The method __init__ runs when a new object is made, and it stores the values. The next program defines two small classes and checks the chain in a function:

Python · editable
True
False
False
False

The first user passes all three checks, so the result is True. The second user has no address, so user.address is not None is False, and Python never reads city. The third value is None itself, so the first check stops everything. The fourth user has an address with a city that is not London, so the last comparison is False.

The order of the three parts is what protects the program. Each part runs only when the parts before it are true. Moving the first check to the end would bring back the error. Here is that version, using a method on the user:

class User:
    def get_address(self):
        return None
 
 
nobody = None
result = nobody.get_address() is not None and nobody is not None
print(result)
Traceback (most recent call last):
  File "null_chain.py", line 7, in <module>
    result = nobody.get_address() is not None and nobody is not None
             ^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get_address'

The method call get_address() runs before nobody is not None is checked, so the error happens on the call.

Comparing with == does not call a method

The == operator does not fail when one side is None. In this example, both comparisons give False, and neither stops the program:

Python · editable
False
False

The crash comes only from a method call on None. The next program calls lower on the None value, and it fails:

missing = None
print("Ada" == missing)
print(missing.lower() == "ada")
False
Traceback (most recent call last):
  File "null_equals.py", line 3, in <module>
    print(missing.lower() == "ada")
          ^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'lower'

When you need a method, put the is not None check before it, as in missing is not None and missing.lower() == "ada".

Giving a default when the value is None

A function often needs a value to work with. Three ways to handle None are shown below. The first is a conditional expression, which is a one-line if and else that gives a value. The lesson on the ternary operator in this module covers it in detail.

The second is the or form from the truthiness section. It is short, but it also replaces the empty string and zero, so use it only when those values are not valid.

The third is to stop with an error message of your own choice. The statement raise starts an error, and ValueError is a standard error type for a value that has the right type but a wrong meaning. The keywords try and except catch the error, so the program can print the message and keep going. They work the same way as try and catch in other languages.

Python · editable
none
missing
caught: code must not be None

Python has no helper function like Objects.requireNonNull in Java. The if code is None check followed by raise does the same job, and it is easy to read.

Reading a condition in order

Python reads a condition from left to right, one part at a time. It stops as soon as the answer is known. The program below runs the test s is not None and len(s) > 0 for three values. It prints the result of the first part next to the result of the whole test:

Python · editable
False False
True False
True True

For None, the first part is False, so Python stops there and never calls len. The whole test is False. For the empty string, the first part is True, so Python measures it. The length is zero, so the whole test is False. For "Ada", both parts are True, and the whole test is True.

Common mistakes

Checking after the call

The most common mistake is putting the check after the call. The condition len(name) > 0 and name is not None fails when name is None, as the example in the and section showed. The call runs first, and the check never gets a turn.

Checking one value and using another

A check protects only the value it names. If the condition checks user and then uses name, the check does not help. The next program has this mistake. It checks user, which is not None, and then measures name, which is None:

name = None
user = "Ada"
if user is not None and len(name) > 0:
    print("has a name")
Traceback (most recent call last):
  File "wrong_value.py", line 3, in <module>
    if user is not None and len(name) > 0:
                            ~~~^^^^^^
TypeError: object of type 'NoneType' has no len()

The message names len, but it does not say which variable was None. Read each call in the condition and ask which value it uses. That value needs its own check before the call.

Using == None instead of is None

Many programs write value == None. For most built-in types it gives the same answer as is None. It is still the wrong test, because a class can define its own ==. The next class does that, and its == always says True:

Python · editable
True
False

The == test asks the object's own __eq__ method, so the object can answer however it likes. The is test asks whether the value is the None object, and no class can change that. Use is None and is not None for every check against None.

Treating an empty string as None

An empty string is not None. The check name is not None is True for "". If you want to reject both, you need two parts, such as name is not None and name != "". The truthiness section showed that if name: rejects both in one step, but it also rejects 0, so pick the form that matches what your value means.

Comparing None with a number

In Python, None cannot be compared with a number using >, < or similar operators. The comparison fails with a TypeError, and the message gives the two types:

count = None
if count > 0:
    print("never")
Traceback (most recent call last):
  File "null_count.py", line 2, in <module>
    if count > 0:
       ^^^^^^^^^
TypeError: '>' not supported between instances of 'NoneType' and 'int'

The check must come first, as in count is not None and count > 0. The count may be zero, and None is not a count, so the check keeps the two cases apart.

Practice

Each exercise has its answer below it. Try to work it out before you read the answer, and run the code if you can.

Exercise 1: What does this print?

s = None
if s is not None and len(s) > 3:
    print("long")
else:
    print("short")

Show the answer

The output is short. The left side s is not None is False, so Python skips len(s) > 3 and runs the else branch.

Exercise 2: Fix the order

The condition below fails when name is None. Rewrite it so that it does not fail, and keep the same meaning.

if len(name) > 0 and name is not None:
    print("has a name")

Show the answer

Put the None check first:

if name is not None and len(name) > 0:
    print("has a name")

The check name is not None is False for a None value, so Python never calls len.

Exercise 3: Write a blank-text test

Write a function is_blank(s) that returns True when s is None, or when s contains only spaces. Test it with None, " " and " a ".

Show the answer

Python · editable
True
True
False

The check s is None comes first in the or, so strip never runs on a None value. The method strip removes spaces from both ends, so " " becomes an empty string and the test is True.

Exercise 4: Check a count that may be None

A variable count can be None or a number. Write a condition that is True only when count holds a number greater than zero.

Show the answer

count is not None and count > 0

The None check comes first. If count is None, the left side is False, and the comparison with zero never runs. Without the check, count > 0 fails with the TypeError shown in the section on comparing None with a number.

Exercise 5: Read the crash

What does this program print, and why does the message name strip?

obj = None
if obj.strip() == "" or obj is None:
    print("empty")

Show the answer

The program prints nothing and stops with an AttributeError. The message says 'NoneType' object has no attribute 'strip'. The left side of or calls strip on obj before the check obj is None is reached. The fix is to swap the parts: obj is None or obj.strip() == "".

Summary

  • None is Python's value for "no value", and a call on it, such as len(x) or x.strip(), stops the program with an error.
  • Test x is None or x is not None before you use x, in the same condition, and do not use == for this test.
  • With and, the left side runs first, and if it is False the right side is skipped. Put the None check on the left.
  • With or, the left side runs first, and if it is True the right side is skipped. Put the None check on the left here too.
  • Each step of a chain such as a.b.c needs its own check, in order.
  • An empty string is not None, and a comparison such as count > 0 fails when count is None.
Check yourself: Else pairing and nulls (8 questions) →Practice this topic: coding problems for Conditionals →

Stuck? Ask the tutor

Ask about anything in this lesson. Answers are short and use simple words.

Sign in to ask the tutor.

← Dangling else and indentation in Python