PythonThe None Type

The None Type

None is Python’s way of representing the absence of a value. It is not zero, not an empty string, and not False — it is a distinct object that specifically means “there is no value here.” None is the sole value of the built-in type NoneType.

None Is a Singleton

There is only ever one None object in a running Python program. No matter how many times None appears in your code, every reference points to the exact same object in memory.

Python
a = None
b = None

print(a is b)          # True -- both refer to the single, shared None object
print(id(a) == id(b))  # True
print(type(a))          # <class 'NoneType'>
Checking for None: Use is, Not ==

Because None is a singleton, the idiomatic and safest way to check for it is with the identity operator is (or is not), not the equality operator ==.

Python
value = None

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

if value is not None:
    print("This won't print")
Warning
Never write `value == None`. It usually works, but it is not idiomatic, and it can be subtly wrong: a custom class could override `__eq__` to make `something == None` return `True` even when `something` is not actually `None`. `is None` cannot be fooled this way because it checks object identity, not a customizable equality method. Linters like `pylint` and `flake8` will flag `== None` as a style violation.
Functions Without a Return Value

Any function that does not explicitly execute a return statement (or that executes a bare return with no value) automatically returns None.

Python
def greet(name):
    print(f"Hello, {name}!")
    # no explicit return statement

result = greet("Ada")
# Hello, Ada!

print(result)         # None
print(result is None) # True
None as a Default Argument Sentinel

None is frequently used as a placeholder default value for a function parameter, signaling “no value was passed” so the function body can decide what to do. This pattern is also how you safely avoid one of Python’s most infamous gotchas: mutable default arguments.

Python
# The classic bug: a mutable default argument is created ONCE,
# when the function is defined -- and then reused across every call!
def add_item_buggy(item, items=[]):
    items.append(item)
    return items

print(add_item_buggy("apple"))   # ['apple']
print(add_item_buggy("banana"))  # ['apple', 'banana']  <- surprise! Same list reused.

# The fix: use None as a sentinel, and create a fresh list inside the function
def add_item_fixed(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

print(add_item_fixed("apple"))   # ['apple']
print(add_item_fixed("banana"))  # ['banana'] -- fresh list every time, as expected
Note
This mutable-default-argument gotcha is covered in full depth in the Functions tutorials. The short version: default argument values are evaluated exactly once, at function definition time, so a mutable default (list, dict, set) is shared across every call that does not override it. Using `None` as the default and creating the real value inside the function body is the standard fix.
Optional[X]: Typing None-or-Something

When you annotate a function or variable with type hints, Optional[X] (from the typing module) documents that a value may be either type X or None. It is shorthand for Union[X, None].

Python
from typing import Optional

def find_user(user_id: int) -> Optional[str]:
    """Returns the username, or None if no user with that id exists."""
    users = {1: "ada", 2: "grace"}
    return users.get(user_id)  # dict.get() returns None if the key is missing

username = find_user(3)
if username is not None:
    print(f"Found: {username}")
else:
    print("User not found")
Note
In Python 3.10+, you can also write `X | None` instead of `Optional[X]` — e.g. `str | None` — which many codebases now prefer since it does not require importing anything from `typing`.
None at a Glance

Question

Answer

Is None falsy?

Yes — bool(None) is False.

Is None equal to 0 or ""?

No — None == 0 and None == "" are both False.

How many None objects exist?

Exactly one, for the lifetime of the program (singleton).

Correct way to check for it?

value is None / value is not None — never ==.

What does a function with no return give back?

None, automatically.

Key Takeaways
  • None represents "no value" and is the only instance of NoneType.

  • It is a singleton — every None in your program is the same object.

  • Always check for it with is None / is not None, never ==.

  • A function without an explicit return implicitly returns None.

  • None is the standard sentinel default for optional parameters, especially to avoid the mutable-default-argument bug.

  • Optional[X] (or X | None in 3.10+) documents that a value may be X or None.