Python – Empty list as a default argument in a python function

This is probably a python “feature” that every junior developer has bumped into – once you make an empty list as a default argument in Python, it works as expected only for the first object of the class. For the second object – not exactly. Don’t worry, everyone has hit that bug, even it they are not willing to admit it.

Nothing related to python, just a nice picture I took from a nice weekend!

The bug actually looks like this:

class Task:
    def __init__(self, title, description, urgency):
        self.title = title
        self.description = description
        self.urgency = urgency


def complete_task(task, grouped_tasks = []):
    task.status = "completed"
    grouped_tasks.append(task.title)
    return grouped_tasks


task1 = Task("Homework", "Physics and Math", 5)
work = complete_task(task1)

task2 = Task("Fun", "Civilization 5 ", 15)
fun = complete_task(task2)

task3 = Task("Sports", "Football", 3)
sports = complete_task(task3)

print("Homework", work)
print("Fun", fun)
print("Sports", sports)

And the result is this one:

Homework ['Homework', 'Fun', 'Sports']
Fun ['Homework', 'Fun', 'Sports']
Sports ['Homework', 'Fun', 'Sports']

However, the correct way to do it is with this function with the “grouped_tasks is None” check:

def complete_task(task, grouped_tasks = None):
    task.status = "completed"
    if grouped_tasks is None:
        grouped_tasks = []
    grouped_tasks.append(task.title)
    return grouped_tasks

And the result looks like this:

Homework ['Homework']
Fun ['Fun']
Sports ['Sports']

The reason why? Well, I explained it in the YouTube video below, but just to underline it once more:

Python evaluates the function when it’s defined. The evaluation has a side effect: any mutable default arguments (lists, dictionaries, etc) are created during evaluation and become part of the function. In our example, a list object is created when the function is evaluated. Now that specific list object is used as the grouped_tasks argument whenever the function is called without a grouped_tasks argument being provided, as the code in the next listing shows.

The above explanation and the nicve picture of optional parameter usage is from the book “Python – How to” by Yong Cui. Get 40% discout with the code watchcui40 –  https://www.manning.com/books/python-how-to
Empty List as Default Argument in a Python Function

Thanks and enjoy it!