A list of lists is easy to flatten with one loop. When lists can be nested at any depth, like [1, [2, [3, [4]]]], you need recursion: a function that calls itself for each inner list.
The program
def flatten(items): result = [] for item in items: if isinstance(item, (list, tuple)): result.extend(flatten(item)) else: result.append(item) return result print(flatten([1, [2, [3, [4, 5]]], 6])) print(flatten([[], [1, (2, 3)], [[[]]], "abc"])) print(flatten([]))
[1, 2, 3, 4, 5, 6] [1, 2, 3, 'abc'] []
How it works
- For each item,
isinstance(item, (list, tuple))asks: is this a list or a tuple? - If it is,
flatten(item)flattens that inner part first, andresult.extend(...)adds all its items to the result. - If it is not, the item is a single value, and
result.append(item)adds it. - Empty lists add nothing, so
[[[]]]disappears completely. - The string
"abc"stays as one item. A string can be looped over like a list, so if the check were "anything you can loop over","abc"would be split into letters. Checking for lists and tuples only avoids that.
Python stops recursion at about 1,000 levels deep (RecursionError). Real data is almost never nested that deeply.
Another way: a generator
A generator gives back items one at a time with yield, instead of building a new list at every level. yield from passes on every item that the inner call yields:
def flatten(items): for item in items: if isinstance(item, (list, tuple)): yield from flatten(item) else: yield item nested = [1, [2, [3, [4, 5]]], 6] print(list(flatten(nested))) print(sum(flatten(nested)))
[1, 2, 3, 4, 5, 6] 21
sum() can use the generator directly, without making a list first.