-1

I am confused trying to solve a task of "flattening" a list of lists.
For example, I've got a list [1, [2, 2, 2], 4] - I need to transform it to [1, 2, 2, 2, 4].
I solved it that way:

def flat_list(array, temp_list=[]):
    for item in array:
        if str(item).isdigit():
            temp_list.append(item)
        else:
            temp_list = flat_list(item, temp_list)

    return temp_list

But when I test it:

assert flat_list([1, 2, 3]) == [1, 2, 3]
assert flat_list([1, [2, 2, 2], 4]) == [1, 2, 2, 2, 4]
assert flat_list([[[2]], [4, [5, 6, [6], 6, 6, 6], 7]]) == [2, 4, 5, 6, 6, 6, 6, 6, 7]

the value of "temp_list" is being transferred between function calls. The value of "temp_list" in the beginning of the second assert is [1, 2, 3] - the value of "return" of first assert - but not the "[]".

As I guess, this is because I have some misunderstanding of scopes and "return" instruction but I don't understand what exactly.

1 Answers1

1

It's a known issue in Python.

Default parameter values are always evaluated when, and only when, the “def” statement they belong to is executed

Ref: http://effbot.org/zone/default-values.htm

In your code example, the temp_list's default value is evaluated when the def statement is executed. And thus it's set to an empty list. On subsequent calls, the list just keeps growing because the temp_list's default values are no longer evaluated and it keeps using the list instance it created the first time.

This could be a work around:

def flat_list(array, temp_list=None):
    if not temp_list:
         temp_list = []

    for item in array:
        if str(item).isdigit():
            temp_list.append(item)
        else:
            temp_list = flat_list(item, temp_list)

    return temp_list

Here, we have passed None instead of the empty list. And then inside the function body we check the value and initialize an empty list as we need.

masnun
  • 11,635
  • 4
  • 39
  • 50