How to Handle None
and Set Default Values in Python
In Python, None
represents the absence of a value. It's common to need to provide a default value when a variable might be None
.
This guide explores various methods for handling this, including conditional expressions (the ternary operator), the or
operator, and best practices for function arguments.
Using Conditional Expressions (Ternary Operator)
A conditional expression (often called a "ternary operator") provides a concise way to assign a default value if a variable is None
:
def example():
my_var = None
return "default value" if my_var is None else my_var
print(example()) # Output: default value
Alternative syntax, same result:
def example():
my_var = None
return my_var if my_var is not None else "default value"
print(example()) # Output: default value
"default value" if my_var is None else my_var
reads as: "Return 'default value' ifmy_var
isNone
; otherwise, returnmy_var
." Theis
operator is best practice for checking for the singletonNone
.
You can use this also outside a function:
my_var = None
my_var = "default value" if my_var is None else my_var
print(my_var) # Output: default value
Using the or
Operator (for Falsy Values)
The or
operator can be used to set a default value, but be aware of its limitations:
def example():
my_var = None
return my_var or "default value"
print(example()) # Output: default value
my_var = None
my_var = my_var or "default value"
print(my_var) # Output: default value
- The
or
operator returns the left operand if it's truthy; otherwise, it returns the right operand.
Important: or
checks for falsiness, not just None
. This means that empty strings (""
), zero (0
), empty lists ([]
), etc., will also trigger the default value. This is often not what you want when checking for None
.
print(0 or 'default value') # Output: default value (0 is falsy)
print("" or 'default value') # Output: default value (empty string is falsy)
print('hello' or 'default value') # Output: hello ('hello' is truthy)
Only use or
for default values when you specifically want to treat all falsy values (empty strings, 0, False
, empty lists, etc.) the same as None
. If you only want to check for None
itself, use the conditional expression from previous section.
Default Arguments in Functions
None
is frequently used as a default argument value in function definitions:
def get_employee(name=None, age=None):
return {'name': name, 'age': age}
print(get_employee()) # Output: {'name': None, 'age': None}
print(get_employee(age=30)) # Output: {'name': None, 'age': 30}
print(get_employee('Tom Nolan', 30)) # Output: {'name': 'Tom Nolan', 'age': 30}
- Default arguments allow you to call the function without specifying those arguments, providing flexibility.
The Mutable Default Argument Trap (and how to avoid it)
Never use mutable objects (like lists or dictionaries) as default argument values directly. This is a classic Python "gotcha":
def get_address(address={}): # DANGEROUS! Don't do this.
return address
addr1 = get_address()
addr2 = get_address()
addr1['country'] = 'Chile'
print(addr1) # Output: {'country': 'Chile'}
print(addr2) # Output: {'country': 'Chile'} <-- Unexpected!
- The same empty dictionary (
{}
) is created once when the function is defined, and then reused for every call whereaddress
is not provided. Modifyingaddr1
also modifiesaddr2
because they both refer to the same dictionary object.
The Correct Way: Use None
as the default, and create the mutable object inside the function:
def get_address(address=None):
if address is None:
address = {} # Create a NEW dictionary each time
return address
addr1 = get_address()
addr2 = get_address()
addr1['country'] = 'Chile'
print(addr1) # Output: {'country': 'Chile'}
print(addr2) # Output: {} (correct - a new, empty dictionary)
- By using
None
as the default, and creating a new dictionary inside the function, each call gets its own independent dictionary. This avoids the shared mutable default problem.