In Python, functions (or methods) can define default values for arguments. When an argument is omitted during function invocation, the specified default value is used.
def foo(text='Good morning'):
print(text)
foo()
# Good morning
foo(text='Hello')
# Hello
In the example above, the function assigns Good morning
as the default value to text
. If an argument is omitted, the default value is used; otherwise, the explicitly provided value takes precedence.
Setting default parameters can be useful in many cases, but there are important considerations to keep in mind.
Important Consideration When Using Default Arguments #
Although default arguments are convenient, a significant pitfall exists: mutable objects such as lists or dictionaries should not be used as default arguments.
This is because default argument values in Python are evaluated only once at function definition, not upon each function call. Consequently, mutable objects specified as default arguments persist across multiple function calls, leading to unintended modifications.
Example of Unexpected Behavior with Mutable Default Arguments #
Consider the following function, which uses a list as a default argument:
def foo(text_list=[], text='Good morning'):
text_list.append(text)
print(text_list)
foo()
# ['Good morning']
foo()
# ['Good morning', 'Good morning']
foo()
# ['Good morning', 'Good morning', 'Good morning']
foo(text_list=[])
# ['Good morning']
foo()
# ['Good morning', 'Good morning', 'Good morning', 'Good morning']
Since the list text_list
is shared across multiple function calls, elements accumulate in an unintended manner.
Recommended Approach #
To avoid this issue, None
should be used as the default argument, and the list should be initialized within the function.
def foo(text_list=None, text='Good morning'):
text_list = text_list or [] # Initialize as an empty list if None
text_list.append(text)
print(text_list)
foo()
# ['Good morning']
foo()
# ['Good morning']
foo()
# ['Good morning']
foo(text_list=[])
# ['Good morning']
foo()
# ['Good morning']
By implementing this approach, a new list is properly initialized for each function invocation, preventing undesired side effects.