I'm trying to map a function that takes 2 arguments to a list:
my_func = lambda index, value: value.upper() if index % 2 else value.lower()
import string
alphabet = string.ascii_lowercase
n = map(my_func, enumerate(alphabet))
for element in n:
print(element)
This gives me a TypeError: <lambda>() missing 1 required positional argument: 'value'
.
What is the correct way to map my lambda onto this input?
Python cannot unpack lambda parameters automatically. enumerate
returns a tuple
, so lambda
has to take that tuple as sole argument
You need:
n = map(lambda t: t[1].upper() if t[0] % 2 else t[1], enumerate(alphabet))
Considering now the ugliness of map
+ lambda
+ manual unpacking, I'd advise the alternate generator comprehension instead:
n = (value.upper() if index % 2 else value for index,value in enumerate(alphabet))
(I removed the lower()
call since your input is already lowercase)
map
will pass each value from enumerate
as a single parameter to the callback, i.e. the lambda
will be called with a tuple as argument. It would be pretty surprising behaviour if map
would unpack arguments which look unpackable, since then its behaviour would depend on the values it iterates over.
To expand iterable arguments, use starmap
instead, which "applies a *
(star)" when passing arguments:
from itertools import starmap
n = starmap(lambda index, value: ..., enumerate(alphabet))
Python can't unpack lambda
parameters automatically.
But you can get round this by passing an extra range
argument to map
:
import string
alphabet = string.ascii_lowercase
n = map(lambda i, v: v.upper() if i % 2 else v.lower(),
range(len(alphabet)),
alphabet)
for element in n:
print(element)
As per the docs:
map(function, iterable, ...)
Return an iterator that applies function
to every item of iterable, yielding the results. If additional
iterable arguments are passed, function must take that many arguments
and is applied to the items from all iterables in parallel. With
multiple iterables, the iterator stops when the shortest iterable is
exhausted. For cases where the function inputs are already arranged
into argument tuples, see itertools.starmap().