Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Why Use the map() Function?

Now that you know how to use the map() function, you’ll review why you might want to use it. You can use this function to write your code in a functional way to input an immutable data structure and define the transformations you want to make, in a declarative way.

When you take this approach, you have a series of steps that are independent from each other and don’t modify your data set. This allows you to keep adding more steps to your program, avoid side effects, and ensure that your data set is still usable.

00:00 Well, if you’re wondering what this is good for—like, mapping functions across a list of things—so here, we could do all kinds of things. Like, we could add all kinds of computed properties, right?

00:10 Like, I could maybe uppercase the name. You can transform your input data in

00:18 all kinds of ways. And the nice thing is if you write your code in this fashion where it’s “functional”, in the sense that you’re taking an input that’s an immutable data structure—so, something that we had up here—and you define those transformations in a

00:36 declarative way like this, or with a list comprehension, or, you know, what we had further down. And you do this, then you have this series of steps that are completely independent from each other. You know, what we did down there—it didn’t modify this list at all.

00:54 It just took this list as an input—or, this tuple as an input, and then generated a new list. We could keep adding more steps to it and they would all be reusable and there would be no side effects.

01:06 Like, we’re not actually reaching into this thing and destroying this data structure or modifying it, but instead, we’re creating a new derived list, or derived iterable, from the input

01:19 data. And that’s kind of a cool concept. It makes things a lot simpler if you’re talking about parallel computation and it’s a very, very powerful concept, just from a mindset perspective, not necessarily from the perspective that you should write all of your Python code exactly like this and always use this style of programming. That would probably drive some people nuts. Here, you learned how to use the map() function. All right!

01:43 So, thanks for listening. Happy Pythoning! I’ll talk to you in the next video.

Avatar image for amicablezebra

amicablezebra on April 16, 2020

Seems slightly sloppy with calling things a ‘list’? Happens kinda frequently when he calls a tuple a list. Sorta freaked me out.

Avatar image for squeakyboots

squeakyboots on April 25, 2021

We started the section with using map() but ended with a more Pythonic way to get to the same result, which is a list comprehension.

So as far as “why use the map() function?” the answer is “don’t”, or at least “don’t have to and it’s actually recommended to use list comprehensions instead”.

The map() function was never executed in this video, just looked at from when it was used previously. Instead we used our new more Pythonic approach of list comprehensions to get our desired result.

Then as far as why use list comprehensions or map(), it’s so we can go back and make transformations in a “declarative” way. We haven’t really talked about how we’re defining “declarative” or it’s benefits, though.

It seems like being “declarative” is a key attribute of functional programming but I’m not sure I get what it means so far.

Avatar image for Bartosz Zaczyński

Bartosz Zaczyński RP Team on April 26, 2021

@squeakyboots One of the criteria for classifying programming languages and programming styles is whether they are imperative or declarative.

The imperative style is when you give precise commands or instructions to the computer, which tell it how to perform an algorithm exactly. It’s the most natural way of expressing a problem in code, for example:

var fruits = Arrays.asList("banana", "orange", "apple");
var result = new ArrayList<String>();
for (String fruit : fruits) {
    if (fruit.endsWith("e")) {
        result.add(fruit.toUpperCase());
    }
}
result.sort(String::compareTo);
System.out.println(result);

This piece of code “micromanages” the computer on a very granular level by giving it step-by-step instructions. However, the same idea could be expressed more abstractly and more compactly using a declarative style, which tells what to do without specifying some of the details like the loop:

var fruits = Arrays.asList("banana", "orange", "apple");
var result = fruits.stream()
        .filter(fruit -> fruit.endsWith("e"))
        .map(String::toUpperCase)
        .sorted()
        .toList();
System.out.println(result);

It reads more like English and has less cognitive clutter. You request actions such as filtering or mapping but leave the implementation of those actions to the underlying layers. Instead, the only pieces to fill in are small fragments of code that you can pass as functions.

The best example of a declarative language is SQL. Again, you specify what to do, e.g., “give me top five employees with the highest salary in descending order” without knowing the exact steps it will translate to. It depends on a database engine you’re using, but even the same database can pick a different strategy for different data volumes, for example.

Avatar image for squeakyboots

squeakyboots on April 26, 2021

Thanks for the explanation and examples!

So in Python imperative might be:

fruits = ["banana", "orange", "apple"]  # list because we're not so worried about mutability with implicit OOP

result = []
for fruit in fruits:  # implicitly define the for loop
    if fruit.endswith('e'):
        result.append(fruit.upper())
result = sorted(result)  # maybe this is still declarative in comparison to writing the sort manually so this snippet would be a hybrid?

print(result)
['APPLE', 'ORANGE']

While declarative might be either of these two:

fruits = ("banana", "orange", "apple")  # tuple to keep things immutable which is more in line with functional programming

result = tuple(
    sorted(
        [fruit.upper() for fruit in fruits if fruit.endswith('e')]
    )
)

result2 = tuple(
    sorted(
        map(lambda y: y.upper(),
            filter(lambda x: x.endswith('e'), fruits))))

print(result, result2)
>>> ('APPLE', 'ORANGE') ('APPLE', 'ORANGE')

Overall I’d say I prefer the second approach, using the list comprehension. Is there extra functionality or some other reason for using map() and filter() instead of a list comprehension or is it just preference?

Avatar image for squeakyboots

squeakyboots on April 27, 2021

I got later in the course and found that the reason to learn map() is because the multiprocessing libraries have their own map() function that works the same way but supports multiprocessing.

So: why use map()? Because it makes life easy when you want to move over to the multiprocessing and concurrent.futures libraries later.

Avatar image for Bartosz Zaczyński

Bartosz Zaczyński RP Team on April 27, 2021

@squeakyboots There’s an upcoming tutorial that will clear this up. In a nutshell, list comprehensions are more Pythonic since they don’t try to hide things from you—they’re more explicit. On the other hand, map() represents a more functional style because it inherently expects a function as an argument. A compelling reason to use map() in a single-threaded environment could be its lazy evaluation. But then again, you could turn your list comprehension into a generator expression to get a similar effect. At the end of the day, it’s a personal preference.

Avatar image for arvindsuds19722005

arvindsuds19722005 on Jan. 3, 2022

Hi,

I get it so far. But what I am not clear, is how will you add elements or remove items without mutating them. How does this happen in Functional Programming language?

Also it will be good if there are some examples to have some Data Structures implemented in FP style. For example binary search tree, Graphs etc..

Sincerely, Sudarsan.D

Avatar image for Bartosz Zaczyński

Bartosz Zaczyński RP Team on Jan. 3, 2022

@arvindsuds19722005 You can’t mutate immutable objects, but you can make a copy of those objects every time you wish to change something in them. For example, Python strings are immutable, yet they expose mutator methods like .upper():

>>> text1 = "Lorem ipsum"
>>> text2 = text1.upper()

>>> text1
'Lorem ipsum'

>>> text2
'LOREM IPSUM'

When you request a string to turn itself into uppercase letters, that doesn’t affect the original object. It results in creating a brand new copy with the desired change applied.

Become a Member to join the conversation.