Python Intermediate: Lambdas, map, and filter

Lambda functions, map, and filter are foundational components in Python that significantly enhance the language's capabilities for concise, functional programming.

Python Intermediate: Lambdas, map, and filter

For more posts about Python, follow the link below.👇👇👇

Exploring Python
Python is frequently utilized in creating websites and software, as well as for automating tasks, analyzing data, and visualizing information.

Previously we discussed topics like iterators, list comprehensions, and generator expressions. If you feel like you need a refresher on that matter, you can find it by following the link. 👇👇👇

Python Intermediate: Iterators, list comprehensions, and generator expressions
Mastering iterators, list comprehensions, and generator expressions is essential. We will take on a journey through these fundamental Python constructs, revealing how they simplify code, boost data processing, and enhance code readability.

Today, we are going to take a look at lambdas, map, and filter functions, powerful yet elegant tools. They are often used in functional programming to perform operations on data without the need for explicit loops.

Lambda functions

Sometimes referred to as "anonymous functions", lambda functions or simply lambdas are a way to create small, inline functions without assigning them a name. They are useful when we need a simple function for a short duration or for specific operations where a full function definition seems unnecessary. For a refresher on the basics of functions in Python follow the link below. 👇👇👇

Python Basics: Functions
Functions are modular blocks of code designed to perform specific tasks. They encapsulate a set of instructions under a meaningful name, making the code more readable, reusable, and manageable.

Lambda functions are defined using the lambda keyword, followed by a list of arguments, a colon, and an expression. The result of the lambda function is the value of the expression. The basic syntax of the lambda function looks as follows.

lambda arguments: expression

A common use of lambda functions is for simple arithmetic operations. Here's a lambda function that calculates the square of a number.

>>> square = lambda x: x**2
>>> square(5)
25

In this example, the lambda function lambda x: x**2 takes one argument x and returns the square of x. As simple as that! A common use case of lambdas is using them along with map or filter functions.

Map

The map function is a built-in function used for applying a given function to each item in an iterable (e.g., a list or tuple). It returns a new iterable with the results of applying the function to each element. Map is a powerful tool for data transformation, as it allows us to process data in an efficient way without the need for explicit loops. The map function is used as follows.

map(function, iterable, ...)

The function is what we want to apply to each element of the iterable. It can be a regular function or a lambda function. The iterable is the sequence (e.g., a list or tuple) that we want to process using the given function.

We can use the map function for simple mapping operations. Let's start with a basic example. Suppose we have a list of numbers, and we want to square each number using a lambda function and map.

>>> numbers = [1, 2, 3, 4, 5]
>>> squared = map(lambda x: x**2, numbers)
>>> squared_list = list(squared)
>>> print(squared_list)
[1, 4, 9, 16, 25]

The lambda function lambda x: x**2 is applied to each element in the numbers list, creating a new iterable squared with the squared values.

We can use map to convert elements from one data type to another. For instance, we can convert a list of integers to a list of strings.

>>> numbers = [1, 2, 3, 4, 5]
>>> string_numbers = map(lambda x: str(x), numbers)
>>> string_numbers_list = list(string_numbers)
>>> print(string_numbers_list)
['1', '2', '3', '4', '5']

The lambda function lambda x: str(x) is applied to each element in the numbers list, creating a new iterable string_numbers with the string values.

We can map multiple iterables by providing more than one iterable as arguments. The function should accept the same number of arguments as there are iterables. For example, we can add corresponding elements from two lists.

>>> list1 = [1, 2, 3]
>>> list2 = [4, 5, 6]
>>> sum_result = map(lambda x, y: x + y, list1, list2)
>>> sum_list = list(sum_result)
>>> print(sum_list)
[5, 7, 9]

The code essentially adds the elements of list1 and list2 together, creating a new list sum_list with the results [5, 7, 9].

Finally, instead of using a lambda function, we can use a custom function with map. For instance, we can have a custom function that capitalizes the first letter of a string.

>>> def capitalize_first_letter(s):
...     return s.capitalize()

>>> words = [f'apple', f'banana', f'cherry']
>>> capitalized_words = map(capitalize_first_letter, words)
>>> capitalized_words_list = list(capitalized_words)
>>> print(capitalized_words_list)
['Apple', 'Banana', 'Cherry']

The above code effectively capitalizes the first letter of each word in the words list using capitalize_first_letter function and stores the modified words in capitalized_words_list.

Let's recall our Car class from previous posts.

class Car:
    def __init__(self, make: str, model: str):
        self.make: str = make
        self.model: str = model

    def __str__(self) -> str:
        return f'{self.make} {self.model}'

    def __repr__(self) -> str:
        return f'{self.make} {self.model}'

We have added the __repr__ method for correct printing into the console output. Now we can try to create a list of cars of a single brand using map function.

>>> models = [f'Camry', f'Corolla', f'Prius', f'Camry', f'Corolla', f'Prius', f'Camry', f'Corolla', f'Prius']
>>> cars = map(lambda model: Car(f'Toyota', model), models)
>>> cars_list = list(cars)
>>> print(cars_list)
[Toyota Camry, Toyota Corolla, Toyota Prius, Toyota Camry, Toyota Corolla, Toyota Prius, Toyota Camry, Toyota Corolla, Toyota Prius]

The provided code initializes a list of car models containing Camry, Corolla, and Prius. It then uses the map function with a lambda expression to create a list of Car objects, each having Toyota as the make and one of the models from the initial list. The resulting cars map object is converted to a list called cars_list, which contains the Car objects. When printed, the output displays a list of Car objects, each representing a Toyota car with a different model.

Filter

Another helpful function is the filter function. It is a built-in function used to filter elements from an iterable (e.g., a list or tuple) based on a specified function (usually a lambda function) that returns either True or False. It returns a new iterable containing only the elements for which the function evaluates to True. The primary use case for the filter function is to selectively extract and process data based on specific conditions.

In general, the filter function syntax is as follows.

filter(function, iterable)

The function takes an element from the iterable and returns either True or False to determine if the element should be included in the output. The iterable is the sequence (e.g., a list or tuple) from which we want to filter elements.

Let's start with a basic example of a filtering operation using a lambda function. Suppose we have a list of numbers, and we want to filter out only the even numbers using a lambda function and filter.

>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> even_numbers = filter(lambda x: x % 2 == 0, numbers)
>>> even_numbers_list = list(even_numbers)
>>> print(even_numbers_list)
[2, 4, 6, 8, 10]

In the above example, the lambda function lambda x: x % 2 == 0 checks whether a number is even, and filter creates a new iterable (even_numbers) containing only the even numbers.

Previously, we have created the following list with cars.

[Toyota Camry, Toyota Corolla, Toyota Prius, Toyota Camry, Toyota Corolla, Toyota Prius, Toyota Camry, Toyota Corolla, Toyota Prius]

filter function can be easily used to filter this list. For that purpose let's extend the Car interface with an is_model method. It will allow us to query for the model of a car so it looks as follows.

class Car:
    def __init__(self, make: str, model: str):
        self.make: str = make
        self.model: str = model

    def __str__(self) -> str:
        return f'{self.make} {self.model}'

    def __repr__(self) -> str:
        return f'{self.make} {self.model}'

    def is_model(self, model: str) -> bool:
        return model in self.model

Now we can easily write a lambda function to filter all the Corollas.

>>> models = [f'Camry', f'Corolla', f'Prius', f'Camry', f'Corolla', f'Prius', f'Camry', f'Corolla', f'Prius']
>>> cars = map(lambda model: Car(f'Toyota', model), models)
>>> filtered_cars = filter(lambda car: car.is_model(f'Corolla'), cars)
>>> print(list(filtered_cars))
[Toyota Corolla, Toyota Corolla, Toyota Corolla]

The provided code first defines a list named models containing repeated car model names. It then uses the map function with a lambda expression to create a collection of Car objects, each labeled as Toyota with one of the models from the models list. Subsequently, the filter function is applied to the cars collection, selecting only the Car objects matching the model Corolla through a defined is_model method. Finally, the code prints a list of Toyota Corolla cars, which are instances of the Car class.

Summary

Lambda functions, map, and filter are essential elements for functional programming and data manipulation. Lambda functions provide a succinct way to create simple functions without formal declarations. Map simplifies applying a function to every element in an iterable, producing a new one with the results. Filter allows for selective extraction of elements based on specified conditions. These features collectively streamline data processing, enhance code readability, and offer invaluable flexibility for Python developers.

What’s next?

Subscribe to receive more posts like this directly to your email!

Python Intermediate: Modules and packages
Modules and packages, together, lay the foundation for constructing well-organized, scalable, and efficient Python applications, where code can be compartmentalized and accessed with ease, ultimately enhancing the developer’s productivity and the codebase’s overall readability.

Ideas💡, questions❔❓ ? Feel free to start the discussion 🗣️🎙️!

Ready for challenges? 👇👇👇

Python Intermediate: Brain teasers
In the world of programming, the road to expertise is paved with challenges. Don’t shy away from solving programming problems; instead, embrace them as opportunities for growth.