Generic pass_many(vals, pass_one) to unroll and call pass_one(val) I'm trying to create a generic function that takes a data structure as input and then sends each non-empty item—e.g.: str, int—individually:

def print_this(v, delim1="", delim2=""):
    print v, delim1, delim2

def pass_many(vals, some_funct, args=None):
    if vals:
        if type(vals) == list or type(vals) == tuple:
            for v in vals:
                if v:
                    pass_many(v, some_funct, args)
        else:
            if args:
                some_funct(vals, *args)
            else:
                some_funct(vals)

&gt;&gt;&gt; pass_many([['foo'],['',(5,3)]], print_this, ["newline","notnewline"])
foo newline notnewline
5 newline notnewline
3 newline notnewline


My current implementation works reasonably well, but feels hacky...

How could I generalise it to unroll all data-structures (except strings), and make it less hacky?
I'd make a few changes: 

1) Take the if v check out of the inner loop into the function body (if not vals: return) - seems more consistent that way, unless you want pass_many(0,print) to print something but pass_may([0], print) not to?

2) I'm not sure there's any reason to use args=None and then check for it being None, rather than just doing args=() to start with, and the implementation's shorter that way.

3) There are definitely better ways to check whether something is a tuple/list/set/etc than using type.  Unfortunately none of them are perfect... I really wish there was a good clean way of distinguishing these things from strings and dictionaries.
Probably he most general thing I can come up with, using Abstract Base Classes from the collections module - it goes over all elements of iterable objects except for mappings (dictionaries etc - unless you want to include those?) and strings (I think the basic string type/s may be different in python3? Not sure.)

from collections import Iterable, Mapping

def pass_many(vals, some_funct, args=()):
    if not vals:
        return
    if isinstance(vals, Iterable) and not isinstance(vals, (basestring, Mapping)):
        for v in vals:
            pass_many(v, some_funct, args)
    else:
        some_funct(vals, *args)


Still, the ABCs aren't perfect - maybe using hasattr checks for whether something is an iterable or a mapping would be better. Not sure. Probably every possible way will have some downsides.  

If you want to be more stringent and just accept plain lists and tuples and no other iterables, isinstance(vals, (list, tuple)) will be fine. It just won't work on things like iterators - whether that matters depends on the intended use.