Getting Started with Map
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.
map
do?
What does 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.
map
Life without 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]
map
implementation
A 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.
map
Passing in multiple iterables to 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.
map
?
Should you be using 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.