[Python-ideas] Suggested MapView object (Re: __len__() for map())

Greg Ewing greg.ewing at canterbury.ac.nz
Sat Dec 1 20:07:16 EST 2018


Steven D'Aprano wrote:
> For backwards compatibilty reasons, we can't just make map() work like 
> this, because that's a change in behaviour.

Actually, I think it's possible to get the best of both worlds.
Consider this:

from operator import itemgetter

class MapView:

     def __init__(self, func, *args):
         self.func = func
         self.args = args
         self.iterator = None

     def __len__(self):
         return min(map(len, self.args))

     def __getitem__(self, i):
         return self.func(*list(map(itemgetter(i), self.args)))

     def __iter__(self):
         return self

     def __next__(self):
         if not self.iterator:
             self.iterator = map(self.func, *self.args)
         return next(self.iterator)

If you give it sequences, it behaves like a sequence:

 >>> a = [1, 2, 3, 4, 5]
 >>> b = [2, 3, 5]
 >>> from math import pow
 >>> m = MapView(pow, a, b)
 >>> print(list(m))
[1.0, 8.0, 243.0]
 >>> print(list(m))
[1.0, 8.0, 243.0]
 >>> print(len(m))
3
 >>> print(m[1])
8.0

If you give it iterators, it behaves like an iterator:

 >>> m = MapView(pow, iter(a), iter(b))
 >>> print(next(m))
1.0
 >>> print(list(m))
[8.0, 243.0]
 >>> print(list(m))
[]
 >>> print(len(m))
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "/Users/greg/foo/mapview/mapview.py", line 14, in __len__
     return min(map(len, self.args))
TypeError: object of type 'list_iterator' has no len()

If you use it as an iterator after giving it sequences, it
also behaves like an iterator:

 >>> m = MapView(pow, a, b)
 >>> print(next(m))
1.0
 >>> print(next(m))
8.0

What do people think? Could we drop something like this in as a
replacement for map() without disturbing anything too much?

-- 
Greg


More information about the Python-ideas mailing list