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

Steven D'Aprano steve at pearwood.info
Sat Dec 1 14:08:03 EST 2018

On Sat, Dec 01, 2018 at 12:28:16PM -0500, David Mertz wrote:
> Other than being able to ask len(), are there any advantages to a slightly
> less opaque map()? Getting the actual result of applying the function to
> the element is necessarily either eager or lazy, you can't have both.

I don't understand the point you think you are making here.

There's no fundamental need to make a copy of a sequence just to apply a 
map function to it, especially if the function is cheap. (If it is 
expensive, you might want to add a cache.)

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):
        self.function = function
        self.wrapped = sequence
    def __len__(self):
        return len(self.wrapped)
    def __getitem__(self, item):
        return self.function(self.wrapped[item])

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.


More information about the Python-ideas mailing list