[Python-ideas] Aid reiteration with new class: gfic

Steven D'Aprano steve at pearwood.info
Fri Jun 19 05:11:11 CEST 2009

On Fri, 19 Jun 2009 07:02:12 am Terry Reedy wrote:
> Backgound:
> Most functions that take an iterable as parameter iterate just once.
> Users of the function can pass any iterable, including iterators.
> The function will call iter(imput) and go.
> If the user wants to iterate thru a virtual collection defined by an
> instance of an iterator class (built-in or user-defined) or generator
> function, the user must call the gf/ic with the appropriate arguments
> and pass the result.

I don't think it's an undue burden on the caller to construct their own 
iterator before calling your function.

To summarise your idea (correct me if I'm wrong):

There are three ways of passing iterable-like arguments:

(A) pass a sequence object like lists; 

(B) pass generators or iterators;

(C) pass a constructor which returns a generator or iterator, plus 
appropriate arguments.

Insider your function, you can easily iterate over (A) or (C) multiple 
times, but not (B).

I don't think there's any way to treat all three cases identically. Your 
proposed gfic class will allow you to treat case (C) just like (A), at 
the cost of expecting the caller to call gfic() rather than pass a 
constructor directly. But the caller still can't pass an iterator in 
place of a sequence or constructor, so you haven't solved anything, 
merely shifted the burden on the user from calling one of:

function(list(constructor(*args, **kwargs)))

to calling one of:

function(gfic(constructor, *args, **kwargs))

As I see it, the correct solution for "my function needs to iterate over 
an iterable twice" is not to expect the caller to pass a sequence, but 
to convert the iterable to a sequence inside your function:

def function(iterable):
    # Iterate over iterable twice
    L = list(iterable)
    for _ in (1, 2):
        for x in L:

Apart from needing to knowing to avoid non-terminating iterators, the 
user need not know whether you walk the input once or twice.

I suppose there is some benefit when dealing with huge iterators, but 
that's probably best dealt with on an ad hoc basis by requiring the 
user to pass a constructor directly.

Steven D'Aprano

More information about the Python-ideas mailing list