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

Terry Reedy tjreedy at udel.edu
Fri Jun 19 08:38:30 CEST 2009


Steven D'Aprano wrote:
> 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.

Only if an iterator is not allowed.

Nor do I think it an undue burden either to wrap the constructor, when 
appropriate, instead of calling it.

> 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.

Right.
> 
> 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),

That is precisely the point.

> at 
> the cost of expecting the caller to call gfic() rather than pass a 
> constructor directly.

See above

> 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)))
> function(list(iterator))
> 
> to calling one of:
> 
> function(gfic(constructor, *args, **kwargs))
> function(list(iterator))

Right. I consider list-avoidance a good thing, more so, it appears than 
you ;-).
> 
> 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:
>             pass
> 
> 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.

Thank you for your response and analysis.

tjr




More information about the Python-ideas mailing list