None is how Python represents “no value”: missing data, optional arguments not passed, or a function that finishes without return. This page explains NoneType, how to test with is None, how None differs from 0, False, and empty containers, and practical uses such as mutable-default fixes and lookups. For how types are reported in general, see type of variable in Python.
Tested on: Python 3.13.3; kernel 6.14.0-37-generic; Ubuntu 25.04.
What is None in Python?
None is a built-in constant and the only instance of NoneType. It is a real object, not a keyword placeholder like “no type.” Use it when a variable, slot, or result has no meaningful value yet, or when “nothing to return” is the right answer.
| Concept | Meaning |
|---|---|
None |
Represents no value or a missing value |
NoneType |
The type whose sole value is None |
is None |
Preferred check for “is this exactly None?” |
is not None |
Preferred check for “this name refers to some object” |
Assigning None means “no value right now,” not “reset to zero” or “clear the string.”
user_id = None
print(user_id)
print(type(user_id))Running this prints None and <class 'NoneType'>.
None vs null in other languages
Python does not have null. The name null is not a keyword; using it raises NameError unless you define it yourself. Use None everywhere you would say “null” in Java, JavaScript, C#, SQL bridges, and similar environments.
try:
null
except NameError as exc:
print(exc.__class__.__name__)Running this prints NameError.
None compared to 0, False, and empty values
None is not the same as 0, False, "", [], or {}. Those are real values of their own types; they are often falsy in if tests, but they are not “missing.”
| Value | Meaning |
|---|---|
None |
No value / missing |
0 |
The integer zero |
False |
Boolean false |
"" |
Empty string (still a string) |
[] |
Empty list |
{} |
Empty dict |
So None == "" and None == 0 are false. When you care specifically about None, test with is None, not with if not x, which also triggers for 0, False, and empty collections.
How to check for None (is None vs == None)
Always prefer is None and is not None. None is a singleton: every reference points to the same object, so identity is what you mean.
== None calls __eq__ on the left-hand object. For most built-ins it still works, but custom classes can override equality in surprising ways, so is None stays predictable.
| Check | Recommended? | Reason |
|---|---|---|
x is None |
Yes | Identity with the single None object |
x is not None |
Yes | Clear and idiomatic |
x == None |
No | Equality can be customized |
x != None |
No | Use is not None |
class Weird:
def __eq__(self, other):
return other is None
w = Weird()
print(w == None)
print(w is None)This prints True then False, which shows why is None is safer for real checks.
if x is None vs if not x
if not x is true for every falsy value: None, False, 0, "", [], {}, set(), (), and similar—not only None.
| Requirement | Use |
|---|---|
Only missing None |
x is None |
| Any falsy “empty” meaning | if not x (know the full list) |
| Zero is a valid value | x is None (not not x) |
| Empty string is valid | x is None |
| “No items” for a list | Often if not items: is fine if None is not used |
For conditionals that must distinguish None from 0 or "", write if x is None: explicitly.
Initial values, function returns, and default arguments
Use None when a name will get a real object later: configuration not loaded, user input not parsed, or a result not computed yet.
Functions without a return expression return None automatically. Calling such a function and printing the result shows None—that is normal, not an error.
Optional parameters often default to None when “caller did not supply this” must be distinguished from a real empty list or dict. That pairs with functions in Python and return-value patterns in returning values from functions.
def log(message, prefix=None):
if prefix is None:
prefix = "[app]"
print(prefix, message)
log("ready")This prints a line starting with [app] because prefix was missing.
None and the mutable default argument pitfall
Never use a mutable object ([], {}, set()) as a default value: it is created once and reused across calls. Use None and allocate inside the body.
def add_item(item, bucket=None):
if bucket is None:
bucket = []
bucket.append(item)
return bucket
print(add_item("a"))
print(add_item("b"))Each call gets its own list: the first line prints ['a'], the second ['b'].
None in dictionaries, lists, and lookups
In a dict, a missing key, a key with value None, and a key with "" or 0 are three different situations. Use key in d, d.get(key, sentinel), or d.get("k") is None only when you already know the key exists or you accept the ambiguity that .get returns None both for “missing” and for “value is None.”
row = {"name": "Ada", "note": None, "tag": ""}
print("missing" not in row)
print(row.get("note") is None)
print(row.get("missing") is None)
print(row["tag"] == "")Running this prints four lines: True, True, True, True. The third True is the subtle one: .get("missing") is None because the key is absent, not because the value was stored as None. If you need to tell those apart, use if "missing" in row: before reading, or pass a sentinel such as row.get("missing", object()).
None inside a list or tuple marks a placeholder slot (missing score, unknown field) while [] still means “empty collection, but present.” That differs from an empty list used as the whole value.
scores = [100, None, 95]
row2 = {"items": [], "items_unknown": None}
print(scores[1] is None)
print(row2["items"] == [])
print(row2["items_unknown"] is None)This prints True three times: the middle score is unknown, items is an empty but real list, and items_unknown means “no list object yet.”
Falsy None and common NoneType errors
None is falsy, so if not x treats it like other falsy values. Do not rely on truthiness when you must separate None from 0 or "".
count = 0
if not count:
print("falsy branch runs for zero too")
missing = None
if not missing:
print("same branch shape as zero—use is None when only None matters")Running this prints both lines: 0 is falsy, so if not count is not the same intent as if count is None.
Typical failures: AttributeError: 'NoneType' object has no attribute '...' when you assumed an object but the variable was None. TypeError when code does arithmetic or ordering with None (for example None < 1 raises TypeError in Python 3). Prefer early checks: if obj is None: return before dereferencing.
label = None
try:
label.split()
except AttributeError as exc:
print(exc.__class__.__name__)
try:
_ = None < 1
except TypeError as exc:
print(exc.__class__.__name__)Running this prints AttributeError then TypeError.
Combining None with any() / all() is easy to get wrong; see Python any() and all() examples when you mix None with other objects.
When to use or avoid None
Use None for missing values, optional arguments not provided, “no result yet,” safe mutable defaults, and explicit “no object” in APIs. Avoid None when an empty list or dict is the natural “empty” value, when 0 or False is meaningful data, or when a different sentinel would read clearer than overloading None.
# Prefer [] when "no items yet" is still a real list you will extend.
items = []
# Prefer None when "not loaded" differs from "loaded and empty."
cache = Noneitems is ready for .append; cache signals “fetch data first” and is not safe to iterate until you assign a real dict or list.
Quick reference
| Task | Approach |
|---|---|
| Assign “no value” | x = None |
| Test missing | x is None |
| Test present | x is not None |
| Test any falsy | if not x (know what that includes) |
| Empty text | "" if length-zero string is meaningful |
| Empty collection | [], {}, etc. |
| Mutable default | def f(a=None): ... then assign inside |
| Implicit return | Functions without return yield None |
Common mistakes
- Writing
nullinstead ofNone. - Using
== Noneinstead ofis Noneon arbitrary objects. - Treating
if not xas “xisNone” when0or""must be allowed. - Confusing “key missing” with “key maps to
None” in dictionaries. - Assuming you can compare
Nonewith numbers for ordering.
Summary
Noneis the single value ofNoneTypeand means “no value” in Python, notnull.- Prefer
is None/is not None; avoid== Nonefor robustness. Noneis falsy but not equal to0,False, or empty containers—test identity when that distinction matters.- Functions without
returngiveNone; optional and mutable-default patterns useNoneas a safe sentinel. - Use explicit
is Nonewhenif not xwould wrongly treat valid0or""as missing.
For a gentler onboarding path, see beginner tips for learning Python.

