Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Python's map() Function: Transforming Iterables
Python’s map() is a built-in function that allows you to process and transform all the items in an iterable without using an explicit for loop, a technique commonly known as mapping. map() is useful when you need to apply a transformation function to each item in an iterable and transform them into a new iterable. map() is one of the tools that support a functional programming style in Python.
In this tutorial, you’ll learn:
- How Python’s
map()works - How to transform different types of Python iterables using
map() - How to combine
map()with other functional tools to perform more complex transformations - What tools you can use to replace
map()and make your code more Pythonic
With this knowledge, you’ll be able to use map() effectively in your programs or, alternatively, to use list comprehensions or generator expressions to make your code more Pythonic and readable.
For a better understanding of map(), some previous knowledge of how to work with iterables, for loops, functions, and lambda functions would be helpful.
Free Bonus: 5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.
Coding With Functional Style in Python
In functional programming, computations are done by combining functions that take arguments and return a concrete value (or values) as a result. These functions don’t modify their input arguments and don’t change the program’s state. They just provide the result of a given computation. These kinds of functions are commonly known as pure functions.
In theory, programs that are built using a functional style will be easier to:
- Develop because you can code and use every function in isolation
- Debug and test because you can test and debug individual functions without looking at the rest of the program
- Understand because you don’t need to deal with state changes throughout the program
Functional programming typically uses lists, arrays, and other iterables to represent the data along with a set of functions that operate on that data and transform it. When it comes to processing data with a functional style, there are at least three commonly used techniques:
-
Mapping consists of applying a transformation function to an iterable to produce a new iterable. Items in the new iterable are produced by calling the transformation function on each item in the original iterable.
-
Filtering consists of applying a predicate or Boolean-valued function to an iterable to generate a new iterable. Items in the new iterable are produced by filtering out any items in the original iterable that make the predicate function return false.
-
Reducing consists of applying a reduction function to an iterable to produce a single cumulative value.
According to Guido van Rossum, Python is more strongly influenced by imperative programming languages than functional languages:
I have never considered Python to be heavily influenced by functional languages, no matter what people say or think. I was much more familiar with imperative languages such as C and Algol 68 and although I had made functions first-class objects, I didn’t view Python as a functional programming language. (Source)
However, back in 1993, the Python community was demanding some functional programming features. They were asking for:
- Anonymous functions
- A
map()function - A
filter()function - A
reduce()function
These functional features were added to the language thanks to the contribution of a community member. Nowadays, map(), filter(), and reduce() are fundamental components of the functional programming style in Python.
In this tutorial, you’ll cover one of these functional features, the built-in function map(). You’ll also learn how to use list comprehensions and generator expressions to get the same functionality of map() in a Pythonic and readable way.
Getting Started With Python’s map()
Sometimes you might face situations in which you need to perform the same operation on all the items of an input iterable to build a new iterable. The quickest and most common approach to this problem is to use a Python for loop. However, you can also tackle this problem without an explicit loop by using map().
In the following three sections, you’ll learn how map() works and how you can use it to process and transform iterables without a loop.
Understanding map()
map() loops over the items of an input iterable (or iterables) and returns an iterator that results from applying a transformation function to every item in the original input iterable.
According to the documentation, map() takes a function object and an iterable (or multiple iterables) as arguments and returns an iterator that yields transformed items on demand. The function’s signature is defined as follows:
map(function, iterable[, iterable1, iterable2,..., iterableN])
map() applies function to each item in iterable in a loop and returns a new iterator that yields transformed items on demand. function can be any Python function that takes a number of arguments equal to the number of iterables you pass to map().
Note: The first argument to map() is a function object, which means that you need to pass a function without calling it. That is, without using a pair of parentheses.
This first argument to map() is a transformation function. In other words, it’s the function that transforms each original item into a new (transformed) item. Even though the Python documentation calls this argument function, it can be any Python callable. This includes built-in functions, classes, methods, lambda functions, and user-defined functions.
The operation that map() performs is commonly known as a mapping because it maps every item in an input iterable to a new item in a resulting iterable. To do that, map() applies a transformation function to all the items in the input iterable.
To better understand map(), suppose you need to take a list of numeric values and transform it into a list containing the square value of every number in the original list. In this case, you can use a for loop and code something like this:
>>> numbers = [1, 2, 3, 4, 5]
>>> squared = []
>>> for num in numbers:
... squared.append(num ** 2)
...
>>> squared
[1, 4, 9, 16, 25]
When you run this loop on numbers, you get a list of square values. The for loop iterates over numbers and applies a power operation on each value. Finally, it stores the resulting values in squared.
You can achieve the same result without using an explicit loop by using map(). Take a look at the following reimplementation of the above example:
>>> def square(number):
... return number ** 2
...
>>> numbers = [1, 2, 3, 4, 5]
>>> squared = map(square, numbers)
>>> list(squared)
[1, 4, 9, 16, 25]
square() is a transformation function that maps a number to its square value. The call to map() applies square() to all of the values in numbers and returns an iterator that yields square values. Then you call list() on map() to create a list object containing the square values.
Since map() is written in C and is highly optimized, its internal implied loop can be more efficient than a regular Python for loop. This is one advantage of using map().
A second advantage of using map() is related to memory consumption. With a for loop, you need to store the whole list in your system’s memory. With map(), you get items on demand, and only one item is in your system’s memory at a given time.
Note: In Python 2.x, map() returns a list. This behavior changed in Python 3.x. Now, map() returns a map object, which is an iterator that yields items on demand. That’s why you need to call list() to create the desired list object.
For another example, say you need to convert all the items in a list from a string to an integer number. To do that, you can use map() along with int() as follows:
>>> str_nums = ["4", "8", "6", "5", "3", "2", "8", "9", "2", "5"]
>>> int_nums = map(int, str_nums)
>>> int_nums
<map object at 0x7fb2c7e34c70>
>>> list(int_nums)
[4, 8, 6, 5, 3, 2, 8, 9, 2, 5]
>>> str_nums
["4", "8", "6", "5", "3", "2", "8", "9", "2", "5"]
map() applies int() to every value in str_nums. Since map() returns an iterator (a map object), you’ll need call list() so that you can exhaust the iterator and turn it into a list object. Note that the original sequence doesn’t get modified in the process.
Using map() With Different Kinds of Functions
You can use any kind of Python callable with map(). The only condition would be that the callable takes an argument and returns a concrete and useful value. For example, you can use classes, instances that implement a special method called __call__(), instance methods, class methods, static methods, and functions.
There are some built-in functions that you can use with map(). Consider the following examples:
>>> numbers = [-2, -1, 0, 1, 2]
>>> abs_values = list(map(abs, numbers))
>>> abs_values
[2, 1, 0, 1, 2]
>>> list(map(float, numbers))
[-2.0, -1.0, 0.0, 1.0, 2.0]
>>> words = ["Welcome", "to", "Real", "Python"]
>>> list(map(len, words))
[7, 2, 4, 6]
You can use any built-in function with map(), provided that the function takes an argument and returns a value.
A common pattern that you’ll see when it comes to using map() is to use a lambda function as the first argument. lambda functions are handy when you need to pass an expression-based function to map(). For example, you can reimplement the example of square values using a lambda function as follows:
>>> numbers = [1, 2, 3, 4, 5]
>>> squared = map(lambda num: num ** 2, numbers)
>>> list(squared)
[1, 4, 9, 16, 25]
lambda functions are quite useful when it comes to using map(). They can play the role of the first argument to map(). You can use lambda functions along with map() to quickly process and transform your iterables.
Processing Multiple Input Iterables With map()
If you supply multiple iterables to map(), then the transformation function must take as many arguments as iterables you pass in. Each iteration of map() will pass one value from each iterable as an argument to function. The iteration stops at the end of the shortest iterable.
Consider the following example that uses pow():