Python Forum
Nested Generator Performance - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Forum & Off Topic (https://python-forum.io/forum-23.html)
+--- Forum: Board (https://python-forum.io/forum-26.html)
+--- Thread: Nested Generator Performance (/thread-4381.html)



Nested Generator Performance - micseydel - Aug-12-2017

(Even though this is still Python, it's not really a question, or any other section, so here I am.)

I often give an interview question to flatten a nested structure, such as [1, 2, [3, [4]], 5]. To do it "greedily" it trivial for most people, but to do it "lazily" is often more of a challenge (especially in other languages). I received a solution like this recently:

def flatten(a):
    for el in a:
        if type(el) == list:
            for el1 in flatten(el):
                yield el1
        else:
            yield el
Until this week, this was basically the solution I always wanted. Sure, isinstance might be preferred, and yield from, and maybe you even want some way to handle iterables other than lists, but the gist of it is there. Right?

Compare it to something like this
def flatten(x):
    stack = [iter(x)]
    while stack:
        try:
            e = next(stack[-1])
        except StopIteration:
            stack.pop()
        else:
            if isinstance(e, list):
                stack.append(iter(e))
            else:
                yield e
That looks so noisy, right? The first one being definitely better?

I'm curious what others thoughts' are on this, and please think about it a bit before checking the spoiler...




RE: Nested Generator Performance - nilamo - Aug-13-2017

My initial impression would be that a non-recursive version would be faster, all other things equal, because function calls are slow in python (and there's known recursion limits). But I ignored that, because I'm dumb :p
Here's what I came up with (before looking at the spoiler).
After seeing your timings (and the fact that your recursive version looks nearly the same as mine), I added the timings:
I stopped timing the greedy one I wrote, since it... too 58 seconds with a depth of 100.