Python Null (None): Guide to Missing Values and NoneType

If you could give nothing a name, what would you call it? Many programming languages, including SQL, Java, and C#, call it “null.” You may have also encountered null pointers or null references in other languages.
In Python, null is called None. It’s easy enough to create, but you’ll need special operators to check for None.
We’ll cover those operators in this article, along with its common uses, best practices, and “gotchas,” so you won’t be left None the wiser about what’s going on.
What is “Null” in Python?
Null traditionally represents missing information or the absence of a value. Think of null more like a concept than a specific value. It signals that a value is missing, unavailable, or intentionally absent. Python labels missing values with the keyword None. It’s a falsy Python object but not equivalent to other falsy values like the empty string, zero, or a blank list. You’ll see None as a default parameter value, as a return value from functions, within collection-like data structures, and on its own.
None in Python: Defining Null Objects and Its Data Type
You assign None in Python using its built-in keyword:
Remember to capitalize None, since Python is case sensitive. Also note that None is a NoneType object:
This shows that None has the type NoneType. Python creates the None object for you, you won’t need to instantiate it yourself.
None is a singleton object, meaning Python creates only one None object in memory. Every variable assigned to None references the same object:
We assign a and b to None, which refers to the same memory object; this is why a is b returns True.
Checking for None: is Operator and Comparisons
Once you have Python’s null value floating around in your code, the next logical step is checking for it, especially in conditionals. The recommended way to check for None relies on the is identity operator:
Likewise, the compound operator is not lets you do a negative check:
The identity operator (is) is preferred over the equality operator (==) when checking for null in Python. The is operator checks object identity, meaning it determines whether two variables reference the exact same object in memory. == can work for None, but it’s not guaranteed to behave consistently across custom objects. None represents the absence of a value, not a value that needs to be compared. Because of this, we don’t care about equivalence. We care about whether a variable points to None, a singleton object. Using is None makes that intent explicit and avoids any edge cases where equality behavior could be customized.
As a rule: use is / is not for None, and reserve == for value comparisons.
The Most Common Uses of None
Now that you know how to create and check for None in Python, let’s explore some of the typical places None appears.
None as a Default Parameter for Function Arguments
Perhaps the most common way to use None is as a default value for a function parameter. Parameters show up in parentheses just after the function’s name in its definition, and you may give them a default value following the pattern of variable_name = default_value. If you don’t provide an argument value for an optional parameter when calling the function, Python uses the default.
Here’s an example function to greet the user. If no function argument is provided for name, the parameter defaults to None, and the function prints a generic greeting:
Better than falling back on an empty string, using None as the default for an optional function argument lets you detect when a value was omitted and handle that case separately inside the function.
None as the Default Return Value
Every Python function returns a value, even if you don’t explicitly program it to do so. Consider the code for this simple greeter that has no return statement:
The function prints a greeting but doesn’t include a return statement, so Python returns None by default. You can verify that by checking that output has the type NoneType:
A function whose primary purpose is a side effect like printing, writing to a file, creating a data visualization, and so on often returns None. Python also returns None when a function contains a return statement without a value. Because None is the default return value, you’ll often encounter it when working with functions that don’t explicitly return anything.
None Values in Data Structures
None can also appear as a valid element inside collections such as lists and dictionaries, where it often represents a placeholder for missing data. For example, this list contains a mix of user names and unknown values:
You’ll also see None as dictionary values. (It’s also a valid key, but that’s less common.) Here, user has a phone field, but no phone number has been provided:
Because None is a regular Python object, you can store it in collections just like strings, numbers, and other values.
None vs NaN in Python
If you’ve ventured into the world of NumPy or pandas, you’ve likely encountered NaN, which stands for “not a number.” It’s tempting to draw parallels between None and NaN, since both feel “null-like” and are associated with missing or unknown values. There are, however, some major distinctions to keep in mind.
Feature | None | NaN |
|---|---|---|
Definition | Absence of a value | Invalid/undefined numeric value |
Type | NoneType | float |
Usage | General purpose | Numerical/analytical workflows |
Comparison | Use | Use |
The following code demonstrates NaN in Python through the built-in math library:
But here’s the biggest NaN gotcha:
Unlike None, a NaN value is not considered equal to itself, making functions like math.isnan() absolutely critical for detection.
Handling Missing Values: Best Practices
Entire books have been written about best practices when handling null values, but we’ll keep it brief. As your skills with Python’s null value, None, increase, here are some ways you can level up your code.
None in Type Hints
Unlike other programming languages like C and Java, Python dynamically types its variables, meaning you don’t need to declare each kind of variable you create. This boosts coding speed but can lead to confusion later, especially in user-defined Python functions.
Type hinting, introduced in Python 3.5 (2015), improves readability and debugging. You can use type hints to define the expected input and output types of a function. For instance, this greeter anticipates one input, name, which is a string, and returns None:
As shown earlier, None often serves as a default value:
But what does this mean for type hinting? It turns out you can tell Python to expect a string or None for the name parameter by joining these types with a pipe:
Type hints improve readability by making it clear that None is an expected value, not an accidental input. Also note, this syntax for type hinting (str | None) was introduced with Python 3.10 (2021), so for legacy systems, you may see Optional imported from the typing library and applied as Optional[str] instead.
Guard Early, Don’t Nest
You’ll find None particularly useful as a default function parameter, but take care not to over-nest conditionals with many requirements. Highly nested logic is much harder to read. For example, say you’d like to discount luxury items to 90% original prices. Here’s a nested Python function to do that:
While this function fulfills its purpose, it’s tough to quickly understand which items actually get the discount.
Instead of nesting, rewrite the function using guard clauses to handle special cases early:
Guard clauses keep None handling at the top of the function so the remaining logic only deals with meaningful, valid values–improving readability and reducing bugs.
Common Bugs and How to Avoid Them
Despite your efforts to follow best practices for null in Python, bugs are bound to show up sooner or later. Keep reading for some of the most common ones and how you can dodge them.
Forgetting a return Statement
As you saw before, Python functions always return something and default to None if no return value is specified. Your function might accidentally give back None if you forget to include a return statement:
In this case, the function performs a calculation but does not return the result, so Python implicitly returns None.
This is one of the most common beginner mistakes, and it can cause issues later if the function result feeds into further calculations. Avoid this gotcha by ensuring functions that are meant to return a value explicitly include a return statement, and always test function outputs before using them in downstream logic.
Chained Method Calls on None (AttributeError)
Python objects often support method chaining, where the result of one method call is immediately used by the next:
The problem is that unlike strings, lists, or user-defined objects, None doesn’t have any methods or attributes. If you attempt to chain methods on it, you’ll get an error. This function looks for a user by ID. Since no user exists with ID 3, the dictionary lookup returns None. Python then raises an AttributeError when you try to call .upper() on that None value:
If a value is None in Python, any chained method calls on it fail immediately with an AttributeError. Always check for None before performing additional operations on a value.
Wrapping Up
If you’re looking for a null value in Python, None is it. This special singleton object represents the absence of a value and most commonly appears as a default return value or parameter for a function argument. Use is None or is not None to check for it, and remember that NaN, or not a number, serves a different purpose despite also being associated with missing data.
When working with None, add guard clauses early, use type hints where appropriate, and be careful not to accidentally return None by leaving out your return statement.
Lots to None tips to remember? You betcha. Take some time to interact with the AI Tutor to cement your newfound knowledge:
- Python Return Multiple Values: 4 Methods & Examples
- Python Multiline Strings: The Complete Guide
- Python not Operator: The Complete Guide to Logical Negation
- Python Print New Line: Methods, Examples, and Best Practices
- Python Exponent: 5 Methods for Exponentiation + Applications
- Python Modulo Operator (%): Complete Guide with Examples
- Python Division: Operators, Floor Division, and Examples
- Python Switch Statement 101: Match-case and alternatives
- Python glob Module: File Pattern Matching Explained
- Binary search in Python 101: Implementation and use cases
Kimberly Fessel