[Python-ideas] __len__() for map()
Steven D'Aprano
steve at pearwood.info
Sat Dec 1 11:53:20 EST 2018
On Sat, Dec 01, 2018 at 11:07:53AM -0500, Paul Svensson wrote:
[...]
> >Here's a map object I prepared earlier:
> >
> >from itertools import islice
> >mo = map(lambda x: x, "aardvark")
> >list(islice(mo, 3))
> >
> >If I now pass you the map object, mo, what should len(mo) return? Five
> >or eight?
>
> mo = "aardvark"
> list(islice(mo, 3))
>
> By what magic would the length change?
> Per the proposal, it can only be eight.
> Of course, that means mo can't, in this case, be an iterator.
> That's what the proposal would change.
I already discussed that: map is not currently a sequence, and just
giving it a __len__ is not going to make it one. Making it a sequence,
or a view of a sequence, is a bigger change, but worth considering, as I
already said in part of my post you deleted.
However, it is also a backwards incompatible change. In case its not
obvious from my example above, I'll be explicit:
# current behaviour
mo = map(lambda x: x, "aardvark")
list(islice(mo, 3)) # discard the first three items
assert ''.join(mo) == 'dvark'
=> passes
# future behaviour, with your proposal
mo = map(lambda x: x, "aardvark")
list(islice(mo, 3)) # discard the first three items
assert ''.join(mo) == 'dvark'
=> fails with AssertionError
Given the certainty that this change will break code (I know it will
break *my* code, as I often rely on map() being an iterator not a
sequence) it might be better to introduce a new "mapview" type rather
than change the behaviour of map() itself.
On the other hand, since the fix is simple enough:
mo = iter(mo)
perhaps all we need is a depreciation period of at least one full
release before changing the behaviour.
Either way, this isn't a simple or obvious change, and will probably
need a PEP to nut out all the fine details.
--
Steve
More information about the Python-ideas
mailing list