[Python-ideas] __len__() for map()

E. Madison Bray erik.m.bray at gmail.com
Thu Nov 29 10:32:00 EST 2018


On Thu, Nov 29, 2018 at 3:43 PM Steven D'Aprano <steve at pearwood.info> wrote:
>
> On Thu, Nov 29, 2018 at 02:16:48PM +0100, E. Madison Bray wrote:
>
> > Okay, let's keep it simple:
> >
> > m = map(str, [1, 2, 3])
> > len_of_m = None
> > if len(m.iters) == 1 and isinstance(m.iters[0], Sized):
> >     len_of_m = len(m.iters[0])
> >
> > You can give me pathological cases where that isn't true, but you
> > can't say there's no context in which that wouldn't be virtually
> > guaranteed
>
> Yes I can, and they aren't pathological cases. They are ordinary cases
> working the way iterators are designed to work.
>
> All you get is a map object. You have no way of knowing how many times
> the iterator has been advanced by calling next(). Consequently, there is
> no guarantee that len(m.iters[0]) == len(list(m)) except by the merest
> accident that the map object hasn't had next() called on it yet.
>
> *This is not pathological behaviour*. This is how iterators are designed
> to work.
>
> The ability to partially advance an iterator, pause, then pass it on to
> another function to be completed is a huge benefit of the iterator
> protocol. I've written code like this on more than one occasion:

That's a fair point and probably the killer flaw in this proposal (or
any involving getting the lengths of iterators).  I still think it
would be useful to be able to introspect map objects, but this does
throw some doubt on the overall reliability of this.  I'd say that in
most cases it would still work, but you're right it's harder to
guarantee in this context.

One obvious workaround would be to attach a flag indicating whether or
not __next__ has been called (or as long as you have such a flag, why
not a counter for the number of times __next__ has been called)?  That
would effectively solve the problem, but I admit it's a taller order
in terms of adding API surface.


More information about the Python-ideas mailing list