48

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Cameron Sparr
  • 3,925
  • 2
  • 22
  • 31

5 Answers5

92

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
18

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);
Jason Sperske
  • 29,816
  • 8
  • 73
  • 124
11

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]
shapr
  • 1,676
  • 13
  • 18
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.

Jonas Dahlbæk
  • 161
  • 2
  • 4
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.

Armin Rigo
  • 12,048
  • 37
  • 48
  • The problem is that we want to avoid the for loop – mleger45 May 09 '16 at 18:47
  • Why? Because it's clearer? Or because of some misconception like "for loops are slow in Python"? – Armin Rigo May 14 '16 at 12:03
  • 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 – mleger45 May 27 '16 at 13:28