Skip to content
Advertisement

Default Parameter Confusion

I know that Python’s default parameters are only evaluated when the function is created, but I’m confused in my example why my first default parameter is getting reset each time but my empty set isn’t.

In the below, I am calling the main_func() from somewhere else with a list of dates. Then iterating through the dates to collect a bunch of data from some api. I need to get at least 100 unique pieces of data for each date, so I repeat the __get_data_for_date function for each date until their are 100 responses. When I then go onto the next date, the start_index gets reset to 0, but my unique_data set keeps the data from before.

Why does start_index get reset but not unique_data?

# when called from main_func, start_index is always reset but unique_data always keeps its data from the previous calls
def __get_data_for_date(date, start_index=0, unique_data=set()):
    data = api_call(date)

    data_set = unique_data

    for d in data:
        data_set.add(d['id'])

    if len(unique_data) < 100:
        return __get_data_for_date(date, start_index=start_index+len(data), unique_data=data_set)

    return data_set

def main_func(dates):
    final_data = []

    for date in dates:
        # start_index is back to 0 but unique_data still has the previous data
        data = __get_data_for_date(date)
        final_data.append(data)

    return final_data

Advertisement

Answer

start_index is never reset. It was never changed in the first place.

start_index is a number, which is immutable. Since it’s immutable, it can never change.

Compare that to a set, which is mutable, and can change. When you do data_set.add(d['id']), you are directly mutating (altering) the object that is stored as the default argument.

So, in both cases, the object that is stored as the default argument never changes (you can verify that by checking the id of each). The difference is that the immutable number is never itself altered, while the mutable set is.


Although, to be clear, the problem isn’t that the set is mutable. The problem is that it’s mutated. It’s safe to have a mutable default argument if you never mutate it (assuming you don’t forget that it’s a default argument in the future).

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement