Codementor Events

Getting Started with Map

Published Jul 17, 2019

While certainly less common, it's perfectly possible to write Python code in a functional style, and there are plenty of tools in the Python standard library to faciliate functional programming. One such tool is called map, and in this post we're look at what map is for, and how you might use it in your own code.

What does map do?

Put simply, map is used to call a function a number of times, each time passing in a new argument from a collection of objects. For example, we might have a list of integers like this:

numbers = [1, 3, 4, 2, 11, 6]

Here, we might use map to double each of the integers in the numbers list. In this case, we'd want to get 6 numbers back: 2, 6, 8, 4, 22, and 12 respectively.

Life without map

Before we look at a map implementation of this, how might we solve this problem without map? Well, we can use a good old for loop.

numbers = [1, 3, 4, 2, 11, 6]
doubled_numbers = []

for number in numbers:
    addition_results.append(number * 2)

That certainly works, but if you've read my post on comprehensions, you know exactly what we're going to do to make this even better:

numbers = [1, 3, 4, 2, 11, 6]
doubled_numbers = [number * 2 for number in numbers]

A map implementation

Now we've seen the alternatives, how do we implement this doubling process using map?

Initially, let's look at the long way. First, we're going to define a function called double, which is going to take care of all the logic for us. double will have a single parameter, and will return double the value of the number passed into the function:

def double(x):
    return x * 2


numbers = [1, 3, 4, 2, 11, 6]

We could certainly do a lot more with this function. We could add error handling and all that good stuff, but this will do for our example.

Now we have our function set up, we can make use of map. map has two required parameters: the first is a function to call, and the second is an iterable object, like a list or a string.

With this in mind, we can implement our map solution like so:

def double(x):
    return x * 2


numbers = [1, 3, 4, 2, 11, 6]
doubled_numbers = map(double, numbers)

There are a couple of things to take note of here. First, we didn't call the double function when passing it in as an argument to map; instead, we simply passed in the function name. map is going to do the calling for us.

The second thing of note is currently hidden. What is the value of doubled_numbers? Well, let's check:

print(doubled_numbers)  # <map object at 0x7f842a9a70f0>

That's certainly not what we wanted. What happened to all our numbers?

map actually returns an iterator, not a collection like a list. This means we can access the values one at a time using something like next:

print(next(doubled_numbers))  # 2
print(next(doubled_numbers))  # 6

If we want our values all at once in something like a list, we can just convert the map object using the relevant factory function:

doubled_numbers = list(map(double, numbers))
print(doubled_numbers)  # [2, 6, 8, 4, 22, 12]

Earlier I said this is the long way, so next we'll take a look at how we can shorten the code a bit.

map with lambda functions

For simpler operations, like our double function, we probably wouldn't bother with a full blown function definition. That is unless we expected to use it in several places in our code. If that's not the case, we can use a lambda function directly inside of map instead.

Using a lambda, our map solution might look like this:

numbers = [1, 3, 4, 2, 11, 6]
doubled_numbers = map(lambda x: x * 2, numbers)

As you can see, this cut down our solution to just a couple of lines. We could make it even shorter by putting the numbers list directly in the map function.

Passing in multiple iterables to map

One interesting thing with map is that it can handle more than one iterable at a time. When we do this, map will gather one item from each iterable for each iteration until it reaches the end of one of these iterables. It's just like using zip in a loop.

Let's look at an example:

numbers_1 = [7, 1, 3]
numbers_2 = [5, 8, 4]

addition_results = list(map(lambda a, b: a + b, numbers_1, numbers_2))

# [12, 9, 7]

In the code above, we have two lists of numbers, both of which we pass into map. The function we call for each iteration is a lambda function, which takes a number from numbers_1, a number from numbers_2, and then returns the sum.

We can do this with an arbitrary number of iterables, we just have to make sure that the function we want to run can handle the number of arguments we'll be passing to it.

Should you be using map?

Before wrapping up this post, I just wanted to say a few words on using map in your own code.

First, it's definitely important to know, because you'll encounter map plenty out in the wild, even if you personally don't want to use it.

As for whether you should be using map, that really depends. For me, the comprehension syntax is generally far clearer than using map in most cases. Given how important readability is, I would therefore generally avoid map, but that's just me.

There are, however, cases where a full blown comprehension might be a tad verbose considering how simple the operations we're doing are. In those cases, maybe map would be better. It's really down to context.

Less important is that map is very often a little faster than a comprehension. As such, if you're dealing with a highly performance critical portion of your app, you might want to consider map over a comprehension. That being said, always test your own code, because sometimes map is just plain slower.

Just some things to consider.

Wrapping up

With that, we're done! That's all there is to it when it comes to getting started with map. There are of course far more complicated ways to use map, and we can do far more complex operations as well. The sky's the limit.

If you're interested in learning more about functional programming in Python I'd recommend taking a look at filter and reduce in the official documentation. You can also take a look at functools, itertools, and the operator module.

I hope you learnt something new, and I'll catch you next time.

Discover and read more posts from Phil Best
get started