Python None Explained: Meaning and Best Practices

Published on: July 10, 2026
Reading time: 6 minutes
texto 'None' centralizado com um fundo com as cores do Pyton

Python None represents the absence of a value. It is not zero, an empty string, an empty list, or False. It is a unique singleton object used when a result is missing, a function has no explicit return value, an optional parameter was not provided, or an object has not been initialized yet.

Understanding None prevents common bugs such as calling methods on a missing value, confusing a valid zero with missing data, or using an incorrect comparison. This guide covers identity checks, truthiness, function returns, optional values, default arguments, sentinels, dictionaries, type hints, Pandas, JSON, and practical validation.

Related topics include Python booleans, return statements, and data types.

What Is None?

result = None
print(result)
print(type(result))

The type is NoneType. A normal Python process has one None object, so identity comparison is the correct way to check it.

The official Python constants documentation defines None. The PEP 8 programming recommendations explain comparison style.

Use is None

value = None

if value is None:
    print("No value is available")

For the opposite condition:

if value is not None:
    print("A value is available")

Avoid value == None. Equality can be customized by a class, while is checks whether both references point to the same singleton object. The == versus is guide explains value and identity comparisons.

None Is Falsy, but It Is Not False

print(bool(None))
print(None is False)

bool(None) is false, but None and False are different objects with different meanings.

This condition accepts several falsy values:

if not value:
    print("The value is falsy")

It runs for None, zero, empty strings, empty lists, and other falsy values. Use is None when only missingness should match.

None vs Zero

stock_count = 0
unknown_stock = None

print(stock_count is None)
print(unknown_stock is None)

Zero is valid numerical information. None says the information is unavailable or not assigned. Treating both as equivalent can create incorrect reports and decisions.

None vs Empty String

middle_name = ""
uncollected_name = None

An empty string may mean the field was intentionally left blank. None may mean the field was never collected. The distinction depends on the data model, but it should be defined consistently.

Functions Return None Implicitly

A function without an explicit return statement returns None:

def show_message() -> None:
    print("Hello")


result = show_message()
print(result)

The annotation -> None communicates that the function performs an action rather than returning a useful value.

A Bare return Also Returns None

def print_positive(number: int) -> None:
    if number <= 0:
        return

    print(number)

The bare return exits early and its result is None.

Do Not Assign the Result of In-Place Methods

Many mutating methods return None to emphasize that they change the object:

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

print(numbers)
print(result)

numbers.sort() modifies the list and returns None. Use sorted(numbers) when you need a new sorted list. See sort versus sorted.

Return None for a Missing Result

def find_user(users: list[dict], user_id: int) -> dict | None:
    for user in users:
        if user["id"] == user_id:
            return user

    return None

The caller must check the result:

user = find_user(users, 42)

if user is None:
    print("User not found")
else:
    print(user["name"])

When absence is a normal possibility, returning None can be clear. When absence is exceptional, raising an exception may be better.

Type Hints for Optional Values

Modern annotations use a union with None:

def load_name(user_id: int) -> str | None:
    ...

Older compatible code may use Optional:

from typing import Optional


def load_name(user_id: int) -> Optional[str]:
    ...

The annotation tells editors and type checkers that callers must handle both a string and None. Read the type hints guide for more examples.

Use None as a Default Argument

None is commonly used to avoid mutable default arguments:

def add_item(item: str, items: list[str] | None = None) -> list[str]:
    if items is None:
        items = []

    items.append(item)
    return items

Each call without items creates a new list. This avoids sharing one default list across calls.

When None Is a Valid Argument

Sometimes None itself is meaningful and cannot distinguish “not provided” from “provided as None.” Use a unique sentinel:

_MISSING = object()


def update_profile(name=_MISSING):
    if name is _MISSING:
        print("Keep the current name")
    elif name is None:
        print("Remove the name")
    else:
        print(f"Set the name to {name}")

A private sentinel makes all three states explicit.

None in Dictionaries

user = {
    "name": "Taylor",
    "phone": None,
}

if user["phone"] is None:
    print("Phone number not provided")

Be careful with dict.get():

phone = user.get("phone")

The result is None both when the key is absent and when its stored value is None. Use membership when the distinction matters:

if "phone" not in user:
    print("The field is missing")
elif user["phone"] is None:
    print("The field exists but has no value")

None in Lists

measurements = [12.5, None, 14.0, None, 13.2]
valid_measurements = [
    value for value in measurements if value is not None
]
print(valid_measurements)

Do not use if value when zero is a valid measurement, because it would remove both zero and None.

JSON null Becomes None

import json

payload = '{"name": "Alex", "phone": null}'
data = json.loads(payload)

print(data["phone"] is None)

When Python data is encoded as JSON, None becomes null. Validate API contracts because some services distinguish a missing key from a key containing null.

Database NULL and None

Database drivers commonly map SQL NULL to Python None. The exact query and schema rules still matter. A nullable database column should normally correspond to an optional value in application code.

Pandas Missing Values

Pandas may represent missing data with NaN, NaT, None, or nullable extension values depending on the column type. Do not rely only on is None for a DataFrame column. Use Pandas missing-value tools:

import pandas as pd

series = pd.Series([1, None, 3])
print(series.isna())

The Pandas beginner guide covers missing values and cleaning.

Avoid AttributeError

This fails when user is None:

# print(user.name)

Check the value at an appropriate boundary:

if user is None:
    raise LookupError("user was not found")

print(user.name)

Do not scatter unnecessary None checks throughout the code. Define clearly which functions may return it and handle it close to the call.

None in Conditions

discount = None

if discount is None:
    final_price = original_price
else:
    final_price = original_price - discount

This keeps a valid zero discount distinct from a missing discount.

Use a Guard Clause

def send_welcome_email(user: dict | None) -> None:
    if user is None:
        return

    print(f"Sending email to {user['email']}")

A guard clause handles the missing case early and keeps the main path less indented. Only use silent return when doing nothing is the correct contract.

Raise Instead of Returning None

For a required configuration, returning None may postpone the failure:

def require_setting(settings: dict, key: str) -> str:
    value = settings.get(key)

    if value is None:
        raise KeyError(f"required setting is missing: {key}")

    return value

The exception handling guide explains when to raise and catch errors.

Test None Behavior

def test_find_user_returns_none_when_missing():
    users = [{"id": 1, "name": "Lee"}]
    assert find_user(users, 99) is None

Also test the non-missing path so the function's complete contract remains protected. See the Pytest guide.

Common Mistakes

  • Comparing with == None instead of is None.
  • Treating zero, empty text, and None as the same state.
  • Forgetting that a function without return produces None.
  • Assigning the result of list.sort() or another in-place method.
  • Calling an attribute or method before checking an optional result.
  • Using dict.get() when missing key and stored None must be different.
  • Using None as a sentinel when it is also a valid input.
  • Filtering with truthiness when zero or empty collections are valid values.

Practical Example: Optional Discount

def calculate_final_price(
    price: float,
    discount: float | None = None,
) -> float:
    if price < 0:
        raise ValueError("price cannot be negative")

    if discount is None:
        return price

    if not 0 <= discount <= price:
        raise ValueError("discount must be between zero and the price")

    return price - discount


print(calculate_final_price(100.0))
print(calculate_final_price(100.0, 0.0))
print(calculate_final_price(100.0, 15.0))

The three calls demonstrate missing discount, a valid zero discount, and a positive discount.

Frequently Asked Questions

Is None the same as null?

None is Python's absence value. Other systems use terms such as null, NULL, nil, or undefined, but their exact semantics may differ.

Why use is instead of ==?

None is a singleton, so identity expresses the intended check and avoids custom equality behavior.

Does None equal False?

No. Both are falsy in boolean contexts, but they are distinct values with different meanings.

Can a function return None?

Yes. It may return it explicitly, through a bare return, or by reaching the end without a return statement.

Should missing data always be None?

No. The correct representation depends on the domain, data source, and whether absence is normal, exceptional, or needs several distinct states.

Conclusion

Python None gives programs a clear representation for absence. Compare it with is None, distinguish it from other falsy values, document optional return types, and check it before using a result.

Use None when one missing state is enough. Use a custom sentinel, exception, or richer data model when the program must distinguish several forms of absence. Clear contracts prevent most None-related bugs.

Share:

Facebook
WhatsApp
Twitter
LinkedIn

Article content

    Related articles

    Ilustração que representa um algoritmo
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    What Is an Algorithm in Programming?

    Learn what an algorithm is in programming with everyday examples, pseudocode, flowcharts, Python implementations, efficiency, testing, and practice tips.

    Ler mais

    Tempo de leitura: 6 minutos
    10/07/2026
    Logo do Python com expressão pensativa e o texto range(), representando a função range no Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python range(): Complete Guide with Examples

    Learn Python range() with start, stop, step, negative values, loops, indexing patterns, performance, common mistakes, and practical beginner examples.

    Ler mais

    Tempo de leitura: 4 minutos
    10/07/2026
    texto 'operadores em Python' com os simbolos de operadores e o logo do Python à direita
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python Operators: Types and Practical Examples

    Learn Python operators with arithmetic, comparison, assignment, logical, membership, identity, bitwise, set, and conditional examples, plus precedence and common mistakes.

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026
    Ilustração representando conjuntos (sets) em Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python Sets: Complete Beginner Guide

    Learn Python sets from scratch: unique values, membership, add and remove methods, union, intersection, differences, subsets, comprehensions, frozenset, and practical

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026
    Programador resolvendo problemas com Python
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Programming Logic with Python for Beginners

    Learn programming logic with Python using algorithms, pseudocode, input and output, conditions, loops, functions, data structures, validation, testing, and a

    Ler mais

    Tempo de leitura: 6 minutos
    10/07/2026
    Código Python com valores Boolean True e False em tela de computador
    Fundamentals
    Foto de perfil de Leandro Hirt da Academify

    Python Booleans: True, False, and Logic

    Learn Python booleans with True and False, comparison and logical operators, truthy and falsy values, identity, membership, short-circuiting, and validation.

    Ler mais

    Tempo de leitura: 5 minutos
    10/07/2026