Skip to main content

Python NoneType Explained

Data Types Satellite

NoneType: The Absence of Value

`None` signals "no value" in Python. Treat it intentionally so APIs communicate when data is optional.

What is None?

  • The single instance of type NoneType—there is only ever one None object.
  • Falsy in a boolean context.
  • The implicit return value of any function that doesn't return anything.
type(None)         # <class 'NoneType'>

def log(msg):
print(msg) # no return statement

log("hi") is None # True — it returned None

Checking for None

Because None is a singleton, test identity with is, never ==:

if result is None:
raise ValueError("No data")

if result is not None:
process(result)

Custom classes can override == to return surprising results, so value == None is unreliable. value is None compares object identity and is always correct—and faster.

None vs empty vs zero

A frequent bug is treating None, 0, and "" as interchangeable. They are all falsy but mean different things:

count = 0        # a real value: zero items
count = None # no value yet / not provided

if count is None: # "was it supplied?"
if not count: # True for 0, "", [], AND None — usually too broad

Use is None when you specifically mean "absent," and reserve truthiness checks for "empty or absent, don't care which."

The mutable default argument trap

Never use a mutable default like [] or {}. Use None as a sentinel and build the real default inside:

def add_item(item, bucket=None):
if bucket is None:
bucket = [] # fresh list on every call
bucket.append(item)
return bucket

A default of bucket=[] is created once and shared across all calls, so it accumulates state between calls—a classic source of bugs.

Common use cases

  • Optional parameters and return values.
  • Sentinel defaults (def save(data=None): ...).
  • Placeholders for values that are computed later.

Next up in your learning path

Frequently Asked Questions

Should I use is None or == None?

Always use is None. None is a singleton, so identity comparison is correct and fast. == None can give wrong answers because a class may override __eq__ to return unexpected results.

if result is None:       # correct
...
if result is not None: # correct

What is the difference between None and 0 or an empty string?

None means "no value at all," while 0 and "" are real values that happen to be falsy. Use is None to detect absence specifically; use a truthiness test only when empty and absent should be treated the same.

count = 0
count is None # False — zero is a real value
if not count: # True for 0, "", [] AND None — often too broad
...

Why should I not use a mutable default argument?

A default like def f(x=[]) is created once when the function is defined, and every call shares it, so it retains data between calls. Use x=None and create the list inside the function to get a fresh one each time.

def add(item, bucket=None):
if bucket is None:
bucket = [] # fresh list every call
bucket.append(item)
return bucket

What does a function return if it has no return statement?

It returns None. The same applies to a bare return with no value. This is why methods that mutate in place, like list.sort(), return None rather than the modified object.

nums = [3, 1, 2]
result = nums.sort() # sorts in place...
result # None — a classic gotcha