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

Terry Reedy tjreedy at udel.edu
Tue Dec 11 13:06:47 EST 2018


On 12/1/2018 2:08 PM, Steven D'Aprano wrote:

> This proof of concept wrapper class could have been written any time
> since Python 1.5 or earlier:
> 

> class lazymap:
>      def __init__(self, function, sequence):

One could now add at the top of the file
    from collections.abc import Sequence

and here

     if not isinstance(sequence, Sequence):
         raise TypeError(f'{sequence} is not a sequence')

>          self.function = function
>          self.wrapped = sequence
>      def __len__(self):
>          return len(self.wrapped)
>      def __getitem__(self, item):
>          return self.function(self.wrapped[item])

For 3.x, I would add

         def __iter__: return map(self.function, self.sequence)

but your point that iteration is possible even without, with the old 
protocol, is well made.

> It is fully iterable using the sequence protocol, even in Python 3:
> 
> py> x = lazymap(str.upper, 'aardvark')
> py> list(x)
> ['A', 'A', 'R', 'D', 'V', 'A', 'R', 'K']
> 
> 
> Mapped items are computed on demand, not up front. It doesn't make a
> copy of the underlying sequence, it can be iterated over and over again,
> it has a length and random access. And if you want an iterator, you can
> just pass it to the iter() function.
> 
> There are probably bells and whistles that can be added (a nicer repr?
> any other sequence methods? a cache?) and I haven't tested it fully.
> 
> For backwards compatibilty reasons, we can't just make map() work like
> this, because that's a change in behaviour. There may be tricky corner
> cases I haven't considered, but as a proof of concept I think it shows
> that the basic premise is sound and worth pursuing.


-- 
Terry Jan Reedy



More information about the Python-ideas mailing list