Iterating over list or single element in python

Viewed 22271

I would like to iterate over the outputs of an unknown function. Unfortunately I do not know whether the function returns a single item or a tuple. This must be a standard problem and there must be a standard way of dealing with this -- what I have now is quite ugly.

x = UnknownFunction()
if islist(x):
    iterator = x
else:
    iterator = [x]

def islist(s):
    try:
        len(s)
        return True
    except TypeError:
        return False

for ii in iterator:
    #do stuff
8 Answers

You might be able to get better performance if you use generators. This should work on python 3.3 and above.

from collections import Iterable

def iterrify(obj):
    """
    Generator yielding the passed object if it's a single element or
    yield all elements in the object if the object is an iterable.

    :param obj: Single element or iterable.
    """
    if isinstance(obj, (str, bytes)):  # Add any iterables you want to threat as single elements here
        yield obj
    elif isinstance(obj, Iterable):  # Yield from the iterables.
        yield from obj
    else:  # yield single elements as is.
        yield obj

I like the approach with Itreable suggested by someone else. Though maybe in some cases the following would be better. It is more more EAFP (https://docs.python.org/3.5/glossary.html#term-eafp) way:

In [10]: def make_iter(x): 
    ...:         try: 
    ...:             return iter(x) 
    ...:         except TypeError: 
    ...:             # We seem to be dealing with something that cannot be itereated over. 
    ...:             return iter((x,)) 
    ...:              

In [11]: make_iter(3)                                                                                                                                                                         
Out[11]: <tuple_iterator at 0x7fa367b29590>

In [13]: make_iter((3,))                                                                                                                                                                      
Out[13]: <tuple_iterator at 0x7fa367b4cad0>

In [14]: make_iter([3])                                                                                                                                                                       
Out[14]: <list_iterator at 0x7fa367b29c90>

This doesn't bothers with checking what we are dealing with. We just try to get an iterator and if it fails, we assume it failed because we were dealing with something that cannot be iterated over (well, it really seems like it cannot be). So we just make a tuple and make an iterator from that.

Related