None is the sole instance of NoneType — there's only ever one None object in a running Python program, which is exactly why `is None` (identity comparison) is preferred over `== None` (equality comparison) when checking for it. Functions that don't explicitly return anything implicitly return None, and it's commonly used as a default placeholder value for optional arguments.
1Understanding NoneType
None is the sole instance of NoneType — there's only ever one None object in a running Python program, which is exactly why is None (identity comparison) is preferred over == None (equality comparison) when checking for it. Functions that don't explicitly return anything implicitly return None, and it's commonly used as a default placeholder value for optional arguments.
Never use a mutable object, like an empty list, as a default argument value; use None as the default and create the mutable object inside the function body instead, since default argument values are evaluated only once, at function definition time, and shared across all calls.
def find_user(user_id, users):
for u in users:
if u["id"] == user_id:
return u
return None
result = find_user(99, [{"id": 1}])
print(result is None)2Practical Example
Here is a real-world application of NoneType showing how it is used in production Python code.
def add_item(item, bucket=None):
if bucket is None:
bucket = []
bucket.append(item)
return bucket
print(add_item("a"))
print(add_item("b"))3Best Practices
Follow these guidelines when working with NoneType:
1. Use is None / is not None instead of == for checking None, since it's both faster and can't be fooled by a custom __eq__
2. Use None as the default value for optional mutable arguments, creating the real object inside the function body
3. Check function return values for None explicitly when a function's docs say it might return 'nothing found'
Tip: Never use a mutable object, like an empty list, as a default argument value; use None as the default and create the mutable object inside the function body instead, since default argument values are evaluated only once, at function definition time, and shared across all calls.
def find_user(user_id, users):
for u in users:
if u["id"] == user_id:
return u
return None
result = find_user(99, [{"id": 1}])
print(result is None)