Search code examples
pythonrecursiongeneratoryield

Recursive call in python seems not to descend


I have a small function to flatten lists and tuples. The recursive call does get invoked, but .. nothing happens.. By "nothing" i mean: the stderr message is not printed and also no results are yielded. That behavior does not make sense, so pointers appreciated. Thx!

def flatten(*arr):
  sys.stderr.write("STDERR: arr is %s\n" %list(arr))
  for a in arr:
    if type(a) is list or type(a) is tuple:
      flatten(a)
    else:
      yield a

print list(flatten(['hi there','how are you'],'well there','what?',[1, 23423,33]))

Solution

  • There are several problems with your function.

    First of all, use isinstance() to simplify the test for sequences:

    for a in arr:
        if isinstance(a, (list, tuple)):
    

    You need to loop over the recursive flatten() call to pass the elements on to the caller, and pass in the list as separate arguments (using the * syntax, to mirror the function signature):

    for sub in flatten(*a):
        yield sub
    

    With these changes the generator works:

    >>> def flatten(*arr):
    ...     for a in arr:
    ...         if isinstance(a, (list, tuple)):
    ...             for sub in flatten(*a):
    ...                 yield sub
    ...         else:
    ...              yield a
    ... 
    >>> print list(flatten(['hi there','how are you'],'well there','what?',[1, 23423,33]))
    ['hi there', 'how are you', 'well there', 'what?', 1, 23423, 33]