Python — Avoid this common mistake of writing functions with default parameters

Verma Varun
2 min readJun 26, 2021
Python default parameters

Writing functions with default arguments seems like a fairly straightforward task. Default the argument in the function definition and you’re all set. That’s right works like a charm as shown in the following example.

def greetings(name, message = "Good Day"):
print(f'Hello {name}. Have a {message}')
greetings('John')
greetings('Daniel')
greetings('Jim', 'Good Afternoon')
greetings('Michael')

Returns the following output. Perfect! All good.

Hello John. Have a Good Day
Hello Daniel. Have a Good Day
Hello Jim. Have a Good Afternoon
Hello Michael. Have a Good Day

Now, let’s try to introduce a mutable argument in the function. We’re printing the time of execution for each statement and giving in a 2 second pause between each call to capture the time increments.

from datetime import datetime
import time
def greetingsWithTime(name, currentTime = datetime.now()):
print(f"Hello {name}. The time is {currentTime.strftime('%B %d, %Y %H:%M:%S')}")
greetingsWithTime('John')
time.sleep(2)
greetingsWithTime('Daniel')
time.sleep(2)
greetingsWithTime('Jim', datetime.now())
time.sleep(2)
greetingsWithTime('Michael')

But, unfortunately, the output is not what you expected. With a timer increment between each call, we expected a new timestamp on each greeting message, but that didn’t happen. But first let’s look at the output you get from running the above code.

Hello John. The time is June 26, 2021 17:26:24 
Hello Daniel. The time is June 26, 2021 17:26:24
Hello Jim. The time is June 26, 2021 17:26:28
Hello Michael. The time is June 26, 2021 17:26:24

Why? Let’s find out. The argument time is a mutable object, and therefore it only gets initialized when the function is first called. The name argument being immutable gets re-initialized every time the function is invoked and therefore picks the new value. As a result, what we see in the function greetingsWithTime is that the first time the method was invoked, the time variable was initialized and continued to hold it’s value.

How do we solve this problem? The solution is not not initialize the argument within the function definition, and instead initialize it within the function body. Transforming the function slightly as shown below would ensure that the value is set properly every time the function is invoked.

def greetingsWithTime(name, currentTime = None):
if currentTime is None:
currentTime = datetime.now()
print(f"Hello {name}. The time is {currentTime.strftime('%B %d, %Y %H:%M:%S')}")

Results in the following output, that we expected.

Hello John. The time is June 26, 2021 17:36:57 
Hello Daniel. The time is June 26, 2021 17:36:59
Hello Jim. The time is June 26, 2021 17:37:01
Hello Michael. The time is June 26, 2021 17:37:03

--

--

Verma Varun

Mastering automation, improving efficiency and connecting systems.