The signature for map is
map(function, iterable[, iterables[, ...]])
In Python 2.x if function is None identity is assumed, and short iterables are padded with 'None' to the length of the longest iterable.
In Python 3.x if function is None you eventually get an exception:
TypeError: 'NoneType' object is not callable
and all iterables are trimmed to the length of the shortest one.
That's a couple of pretty drastic changes. How do I get 2.x semantics back?
Oh, and it now returns an iterator instead of a list, but I'm okay with that change. ;)
This is useful for cases where you don't know ahead of time which function, if any, will be applied -- just because you aren't actually transforming the iterable doesn't mean you don't want its contents.
You must roll your own -- but it's easy:
from itertools import zip_longest, starmap
def map2x(func, *iterables):
if len(iterables) == 1:
zipped = list(iterables[0])
else:
zipped = zip_longest(*iterables)
if func is None:
return zipped
return starmap(func, zipped)
A simple example:
a=['a1']
b=['b1','b2','b3']
c=['c1','c2']
print(list(map2x(None, a, b, c)))
which gives us:
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
If you have only one iterable, like:
map(None, 'hello world')
Then simply replace that with:
list('hello world')
Update:
My original answer here didn't work if you called map() with None as function and only one iterable. That's because nobody does that, since then you can just as well just use list(iterable). But I added the handling of that case anyway, by popular request. :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With