Python 3 replacement for deprecated compiler.ast flatten function

itertools.chain is the best solution for flattening any nested iterable one level – it’s highly efficient compared to any pure-python solution.

That said, it will work on all iterables, so some checking is required if you want to avoid it flattening out strings, for example.

Likewise, it won’t magically flatten out to an arbitrary depth. That said, generally, such a generic solution isn’t required – instead it’s best to keep your data structured so that it doesn’t require flattening in that way.

Edit: I would argue that if one had to do arbitrary flattening, this is the best way:

import collections

def flatten(iterable):
    for el in iterable:
        if isinstance(el, collections.Iterable) and not isinstance(el, str): 
            yield from flatten(el)
        else:
            yield el

Remember to use basestring in 2.x over str, and for subel in flatten(el): yield el instead of yield from flatten(el) pre-3.3.

As noted in the comments, I would argue this is the nuclear option, and is likely to cause more problems than it solves. Instead, the best idea is to make your output more regular (output that contains one item still give it as a one item tuple, for example), and do regular flattening by one level where it is introduced, rather than all at the end.

This will produce more logical, readable, and easier to work with code. Naturally, there are cases where you need to do this kind of flattening (if the data is coming from somewhere you can’t mess with, so you have no option but to take it in the poorly-structured format), in which case, this kind of solution might be needed, but in general, it’s probably a bad idea.

Leave a Comment