Question

Consider the following code:

def my_fun(an_iterable):
  for val in an_iterable:
    do_work(val)
    if some_cond(val):
       do_some_other_work(an_iterable)
       break

if the an_iterable is a list/tuple, do_some_other_work will get the whole list again. But if the an_iterable was a iterator or a generator, it will only receive rest of the items in the list. How do I differentiate between two cases? I want do_some_other_work to receive rest of the items only.

Was it helpful?

Solution

There's no general way to tell whether you can iterate over an object repeatedly. File-like objects, in particular, are likely to screw up checks. Fortunately, you don't need to check this. If you just want to make sure do_some_other_work only gets the rest of the items, you can explicitly request an iterator:

def my_fun(iterable):
    iterable = iter(iterable)
    # Do whatever.

OTHER TIPS

Consider the following snippet:

import types

def which(obj):
    if isinstance(obj, types.GeneratorType):
        print 'Generator'
    elif hasattr(obj, 'next') and (iter(obj) == obj):
        print 'Iterator'
    elif hasattr(obj, '__iter__'):
        print 'Iterable'
    else:
        print 'Object'

def my_gen(length):
    for i in xrange(length):
        yield i

# Reports 'Generator'
which(my_gen(10))
# Reports 'Iterable'
which(iter(xrange(10)))
# Reports 'Object'
which([i for i in xrange(10)])

with open('foo.txt', 'w+') as fout:
    for _ in xrange(10):
        fout.write('hello\n')

# Reports 'Iterable'
with open('foo.txt') as fin:
    which(fin)

This identifies them as 'Generator', 'Iterable' and then 'Object'

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top