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

Steven D'Aprano steve at pearwood.info
Wed Nov 28 10:03:49 EST 2018


On Wed, Nov 28, 2018 at 03:27:25PM +0100, E. Madison Bray wrote:

> I mostly agree with the existing objections, though I have often found
> myself wanting this too, especially now that `map` does not simply
> return a list.  This problem alone (along with the same problem for
> filter) has had a ridiculously outsized impact on the Python 3 porting
> effort for SageMath, and I find it really irritating at times.

*scratches head*

I presume that SageMath worked fine with Python 2 map and filter? You 
can have them back again:

# put this in a module called py2
_map = map
def map(*args):
    return list(_map(*args))


And similarly for filter. The only annoying part is to import this new 
map at the start of every module that needs it, but while that's 
annoying, I wouldn't call it a "ridiculously outsized impact". Its one 
line at the top of each module.

from py2 import map, filter


What am I missing?



> As a simple counter-proposal which I believe has fewer issues, I would
> really like it if the built-in `map()` and `filter()` at least
> provided a Python-level attribute to access the underlying iterables.
> This is necessary because if I have a function that used to take, say,
> a list as an argument, and it receives a `map` object, I now have to
> be able to deal with map()s, and I may have checks I want to perform
> on the underlying iterables before, say, I try to iterate over the
> `map`.
> 
> Exactly what those checks are and whether or not they're useful may be
> highly application-specific, which is why say a generic `map.__len__`
> is not workable.  However, if I can at least inspect those iterables I
> can make my own choices on how to handle the map.

Can you give a concrete example of what you would do in practice? I'm 
having trouble thinking of how and when this sort of thing would be 
useful. Aside from extracting the length of the iterable(s), under what 
circumstances would you want to bypass the call to map() or filter() and 
access the iterables directly?


> Exposing the underlying iterables to Python also has dangers in that I
> could directly call `next()` on them and possibly create some
> confusion, but consenting adults and all that...

I don't think that's worse than what we can already do if you hold onto 
a reference to the underlying iterable:

py> a = [1, 2, 3]
py> it = map(lambda x: x+100, a)
py> next(it)
101
py> a.insert(0, None)
py> next(it)
101



-- 
Steve


More information about the Python-ideas mailing list