50

Here is the loop I am trying to use the map function on:

volume_ids = [1,2,3,4,5]
ip = '172.12.13.122'
for volume_id in volume_ids:
    my_function(volume_id, ip=ip)

Is there a way I can do this? It would be trivial if it weren't for the ip parameter, but I'm not sure how to deal with that.

0

5 Answers 5

94

Use functools.partial():

from functools import partial

mapfunc = partial(my_function, ip=ip)
map(mapfunc, volume_ids)

partial() creates a new callable, that'll apply any arguments (including keyword arguments) to the wrapped function in addition to whatever is being passed to that new callable.

Sign up to request clarification or add additional context in comments.

Comments

19

Here is a lambda approach (not better, just different)

volume_ids = [1,2,3,4,5]
ip = '172.12.13.122'
map(lambda ids: my_function(ids, ip), volume_ids);

1 Comment

partials are faster, lambdas support out of order arguments
12

This can be done easily with a list comprehension.

volume_ids = [1,2,3,4,5]
ip = '172.12.13.122'
results = [my_function(i,ip=ip) for i in volume_ids]

2 Comments

This has side effects. You are assigning a bunch of memory that may not be desired (and wasn't specified by OP).
@aydow Why didn't you complain about the same thing under the other answers?
3

In general, one can use map to pass keywords to a function by wrapping that function in something which unpacks a dictionary, and then passing an iterable of dictionaries to map. Example:

from itertools import product

volume_ids = [1,2,3,4,5]
volume_ids = (("volume_id", volume_id) for volume_id in volume_ids)
ips = [("ip", '172.12.13.122')]
kwargs_iterable = map(dict, product(volume_ids, ips))

result = map(lambda kwargs: my_function(**kwargs), kwargs_iterable)

For your special case, however, a simpler solution would be:

map(my_function, volume_ids, [ip]*len(volume_ids))

This is concise and does not rely on any imports. Another possibility could be to combine product and starmap from itertools:

from itertools import product, starmap

ips = [ip]
starmap(my_function, product(volume_ids, ips))

This generalizes nicely to the setting with more than one ip adress, or more than two variables.

Comments

0

How about this?

results = []
for volume_id in volume_ids:
    results.append(my_function(volume_id, ip=ip))

This is three lines of code instead of one --- it's three lines of clear and obvious code instead of importing some special-case helper from module such-and-such. This argument is probably a matter of taste, but it has a lot of weight depending on who you talk to.

3 Comments

The problem is that we want to avoid the for loop
Why? Because it's clearer? Or because of some misconception like "for loops are slow in Python"?
Yes, I would say indeed is clearer, more Pythonish, and map function is meant to perform the laziest iteration posible. Besides, we need a list back, so map would perform it better for us than writing more lines coding a for loop

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.