GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • AI Tutor
  • Roadmaps
  • Packs
  • Videos
  • Newsletters

This view

  • Original page
  • New address

GeezerVison is showing roadmap.sh — Python Null (None): Guide to Missing Values and NoneType

Loading...

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

Python Null Explained
Kimberly FesselKimberly Fessel
Prefer us on Google

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.

  • What is “Null” in Python?
  • None in Python: Defining Null Objects and Its Data Type
  • Checking for None: is Operator and Comparisons
  • The Most Common Uses of None
  • None vs NaN in Python
  • Handling Missing Values: Best Practices
  • Common Bugs and How to Avoid Them
  • Wrapping Up

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:

python
x = Noneprint(x) # Expected result:# None

Remember to capitalize None, since Python is case sensitive. Also note that None is a NoneType object:

python
type(x) # Expected result:# <class 'NoneType'>

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:

python
a = Noneb = Noneprint(a is b) # Expected result:# True

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:

python
x = Noneif x is None:    print("x is None")# Expected result:# x is None

Likewise, the compound operator is not lets you do a negative check:

python
if x is not None:    print("x has a value")

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:

python
def greet(name=None):    if name is None:        print("Hi there!")    else:        print(f"Hi, {name}!")greet(name="Sarah")greet()# Expected result:# Hi, Sarah!# Hi there!

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. You will also see the or operator used to supply defaults, though it fires on any falsy value, not just None.

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:

python
def greet_simple():    print("Hi there!")output = greet_simple()print(output)# Expected result:# Hi there!# None

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:

python
print(type(output)) # Expected result:# <class '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. Functions that return multiple values do it explicitly, by packing them into a tuple or another collection.

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:

python
users = ["Sarah", None, "Mike", "Kiki", None]print(users) # Expected result:# ['Sarah', None, 'Mike', 'Kiki', None]

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:

python
user = {    "name": "Sarah",    "subscription": "Pro",    "phone": None}print(user["phone"])# Expected result:# None

Finally, in a linked list, None marks the end of the chain: the last node's next attribute is None.

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 is

Use math.isnan()

The following code demonstrates NaN in Python through the built-in math library:

python
x = float('nan')print(x)print(type(x))print(math.isnan(x))# Expected result:# nan# <class 'float'># True

But here’s the biggest NaN gotcha:

python
print(float('nan') == float('nan'))# Expected result:# False

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, or when setting environment variables (e.g. os.getenv() returns None when an environment variable isn't set)

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:

python
def greet_string(name: str) -> None:    print(f"Hi, {name}!")greet_string("Sarah")# Expected result:# Hi, Sarah!

As shown earlier, None often serves as a default value:

python
def greet(name=None):    if name is None:        print("Hi there!")    else:        print(f"Hi, {name}!")greet()# Expected result:# Hi there!

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:

python
def greet(name: str | None = None) -> None:    if name is None:        print("Hi there!")    else:        print(f"Hi, {name}!")greet()# Expected result:# Hi there!

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:

python
def apply_discount(price, category=None):    if price is not None:        if category == "luxury":            return price * 0.9        return price    return Noneprint(apply_discount(100, category="luxury"))# Expected result:# 90.0

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:

python
def apply_discount(price, category=None):    if price is None:        return None    if category == "luxury":        return price * 0.9    return priceprint(apply_discount(100, category="luxury"))# Expected result:# 90.0

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:

python
def multiply(a, b):    result = a * b product = multiply(2, 3)print(product)# Expected result:# None

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:

python
name = " Sarah  "print(name.strip().upper())# Expected result:# SARAH

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:

python
def find_user(user_id):    users = {        1: "Sarah",        2: "Mike"    }    return users.get(user_id)print(find_user(3).upper())# Expected result:# AttributeError: 'NoneType' object has no attribute 'upper'

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:

You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.