programming
Python
None value
data types
coding fundamentals

What is a None value?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

None is Python's built-in way to represent the absence of a value. It looks simple, but it matters in function design, data validation, and control flow because "missing" is not the same as zero, False, or an empty string.

None Is a Real Object

None is not a keyword that means "ignore this". It is a real singleton object created by Python. Singleton means every reference to None points to the same object, which is why identity checks are the right tool.

python
1value = None
2
3print(value)
4print(type(value))
5print(value is None)
6print(id(value) == id(None))

Typical output shows NoneType, and both identity checks are true. That is the first important rule: when you want to know whether a variable is missing, write is None, not == None.

The reason is practical. Equality can be customized by user-defined classes, but identity cannot. If a class implements unusual equality rules, value == None may behave in surprising ways. value is None always means "this object is the singleton None".

Where None Comes From

You see None in normal Python code even when you did not assign it directly. A function with no explicit return statement returns None. Many APIs also use it to mean "not found" or "not provided".

python
1def log_message(text: str) -> None:
2    print(f"LOG: {text}")
3
4def find_user(users: dict[int, str], user_id: int):
5    return users.get(user_id)
6
7result = log_message("started")
8users = {1: "Ada", 2: "Linus"}
9
10print(result is None)
11print(find_user(users, 1))
12print(find_user(users, 9) is None)

That behavior is useful because None communicates intent. A return value of 0 might be a valid measurement. An empty string might still mean "a value exists, but it is blank". None means no usable value is present.

This distinction becomes important when you design APIs. If a caller needs to tell the difference between "no data" and "empty data", None is often the cleanest signal.

Missing Is Not the Same as Empty

One of the most common beginner errors is collapsing all falsey values into one branch. In Python, None, 0, False, "", and [] are all falsey, but they do not mean the same thing.

python
1def describe_score(score):
2    if score is None:
3        return "score missing"
4    if score == 0:
5        return "score is zero"
6    return f"score is {score}"
7
8print(describe_score(None))
9print(describe_score(0))
10print(describe_score(7))

If you wrote if not score, both None and 0 would land in the same branch. That may be acceptable in a quick script, but it is usually a bug in production logic because a real zero gets mistaken for missing data.

The same idea applies to strings and collections. None usually means the caller omitted a value. "" or [] means the caller supplied a value and it happened to be empty.

None as a Safe Sentinel

None is also a common sentinel value for optional function parameters. This pattern is especially useful when the real default should be created fresh for each call.

python
1def add_item(item: str, bucket=None):
2    if bucket is None:
3        bucket = []
4    bucket.append(item)
5    return bucket
6
7print(add_item("a"))
8print(add_item("b"))
9print(add_item("c", ["existing"]))

Why not write bucket=[] in the function signature? Because default arguments are evaluated once, not once per call. A mutable default list would be reused across calls and leak state between invocations. Using None as the placeholder avoids that bug and makes the function's behavior explicit.

In larger codebases, this pattern also improves readability. A parameter default of None signals that the function will decide what to do when the caller does not provide a value.

Typing Optional Values

If you use type hints, None usually appears as part of an optional type. That tells both readers and static analyzers that "missing" is a valid result.

python
1from typing import Optional
2
3def parse_port(text: str) -> Optional[int]:
4    if not text.isdigit():
5        return None
6    return int(text)
7
8print(parse_port("8080"))
9print(parse_port("dev"))

This is a good design when failure is expected and uncomplicated. The caller can check for None and decide what to do next. If failure is exceptional and should stop execution, raising an exception is usually better.

Common Pitfalls

  • Using if not value when you really need to distinguish None from 0, False, or an empty container.
  • Comparing with == None instead of is None.
  • Forgetting that a function with no explicit return still returns None.
  • Using a mutable default argument where None should be the sentinel.
  • Returning None from an API without documenting that the caller must handle the missing case.

Summary

  • 'None is Python's singleton object for "no value".'
  • Use is None to test for it.
  • Keep None separate from other falsey values in application logic.
  • 'None is a safe and common sentinel for optional parameters.'
  • Optional return types often use None to signal "no result found".

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.