What is lambda in Python

What Is a Lambda Function in Python: Learn By Example

If you are getting started with Python it can be a bit confusing to understand what a lambda is. Let’s see if I can clarify a few things straight away.

A lambda is also called an anonymous function and that’s because a lambda is a function without a name. To define a lambda in Python you use the keyword lambda followed by one or more arguments, a colon (:), and a single expression.

We will start with a simple example of lambda function to get used to its syntax and then we will look at how a Python lambda function fits different scenarios.

To practice all the examples we will use the Python interactive shell.

Let’s get started!

How to Use a Python Lambda Function and Its Syntax

Let’s start with the syntax of a lambda function.

A lambda function starts with the lambda keyword followed by a list of comma-separated arguments. The next element is a colon (:) followed by a single expression.

lambda <argument(s)> : <expression>

As you can see a lambda function can be defined in a single line.

Let’s have a look at a very simple lambda that multiplies the number x (argument) by 2:

lambda x : 2*x

Here’s what happens if we define this lambda in the Python shell:

>>> lambda x : 2*x
<function <lambda> at 0x101451cb0>

We get back a function object. Interestingly when defining a lambda we don’t need a return statement as part of the expression.

What happens if we include the return statement in the expression?

>>> lambda x : return 2*x
  File "<stdin>", line 1
    lambda x : return 2*x
                    ^
SyntaxError: invalid syntax

We receive a syntax error.

So, there is no need to include a return statement in the lambda function syntax.

How to Call a Lambda Function in Python

We have seen how to define a lambda, but how can we call it?

Firstly we will do it without assigning the function object to a variable. To do that we just need to use parentheses.

(lambda x : 2*x)(2)

We will surround the lambda expression with parentheses followed by parentheses surrounding the arguments we want to pass to the lambda.

This is the output of the lambda call:

>>> (lambda x : 2*x)(2)
4

Sweet!

We also have another option. We can assign the function object returned by the lambda function to a variable, and then call the function using the variable name.

>>> multiply = lambda x : 2*x
>>> multiply(2)
4

I feel this kind of goes against the idea of not giving a name to a lambda, but it was worth knowing…

Before continuing reading this article make sure you try all the examples we have seen so far to get familiar with lambdas.

I still remember the first time I started reading about lambdas, I was a bit confused. So don’t worry if you feel the same right now 🙂

Passing Multiple Arguments to a Lambda Function

In the previous sections, we have seen how to define and execute a lambda function.

We have also seen that a lambda can have one or more arguments, let’s see an example with two arguments.

Create a lambda that multiplies the arguments x and y:

lambda x, y :  x*y

As you can see, the two arguments are separated by a comma.

>>> (lambda x, y :  x*y)(2,3)
6

As expected the output returns the correct number (2*3).

A lambda is an IIFE (Immediately Invoked Function Expression). It’s basically a way to say that a lambda function is executed immediately as soon as it’s defined.

Difference Between a Lambda Function and a Regular Function

Before continuing looking at how we can use lambdas in our Python programs, it’s important to see how a regular Python function and a lambda relate to each other.

Let’s take our previous example:

lambda x, y :  x*y

We can also write it as a regular function using the def keyword:

def multiply(x, y):
    return x*y

You notice immediately three differences compared to the lambda form:

  1. When using the def keyword we have to specify a name for our function.
  2. The two arguments are surrounded by parentheses.
  3. We return the result of the function using the return statement.

Assigning our lambda function to a variable is optional (as mentioned previously):

multiply_lambda = lambda x, y :  x*y

Let’s compare the objects for these two functions:

>>> def multiply(x, y):
...     return x*y
... 
>>> multiply_lambda = lambda x, y :  x*y
>>> multiply
<function multiply at 0x101451d40>
>>> multiply_lambda
<function <lambda> at 0x1014227a0>

Here we can see a difference: the function defined using the def keyword is identified by the name “multiply” while the lambda function is identified by a generic <lambda> label.

And let’s see what is returned by the type() function when applied to both functions:

>>> type(multiply)
<class 'function'>
>>> type(multiply_lambda)
<class 'function'>

So, the type of the two functions is the same.

Can I use If Else in a Python Lambda?

I wonder if I can use an if else statement in a lambda function…

lambda x: x if x > 2 else 2*x

This lambda should return x if x is greater than 2 otherwise it should return x multiplied by 2.

Firstly, let’s confirm if its syntax is correct…

>>> lambda x: x if x > 2 else 2*x
<function <lambda> at 0x101451dd0>

No errors so far…let’s test our function:

>>> (lambda x: x if x > 2 else 2*x)(1)
2
>>> (lambda x: x if x > 2 else 2*x)(2)
4
>>> (lambda x: x if x > 2 else 2*x)(3)
3

It’s working well…

…at the same time you can see that our code can become more difficult to read if we make the lambda expression more and more complex.

As mentioned at the beginning of this tutorial: a lambda function can only have a single expression. This makes it applicable to a limited number of use cases compared to a regular function.

Also remember…

You cannot have multiple statements in a lambda expression.

How to Replace a For Loop with Lambda and Map

In this section we will see how lambdas can be very powerful when applied to iterables like Python lists.

Let’s begin with a standard Python for loop that iterates through all the elements of a list of strings and creates a new list in which all the elements are uppercase.

countries = ['Italy', 'United Kingdom', 'Germany']
countries_uc = []

for country in countries:
    countries_uc.append(country.upper())

Here is the output:

>>> countries = ['Italy', 'United Kingdom', 'Germany']
>>> countries_uc = []
>>> 
>>> for country in countries:
...     countries_uc.append(country.upper())
... 
>>> print(countries_uc)
['ITALY', 'UNITED KINGDOM', 'GERMANY']

Now we will write the same code but with a lambda. To do that we will also use a Python built-in function called map that has the following syntax:

map(function, iterable, ...)

The map function takes another function as first argument and then a list of iterables. In this specific example we only have one iterable, the countries list.

Have you ever seen a function that takes another function as argument before?

A function that takes another function as argument is called an Higher Order Function.

It might sound complicated, this example will help you understand how it works.

So, what does the map function do?

The map function returns an iterable that is the result of the function passed as first argument applied to every element of the iterable.

In our scenario the function that we will pass as first argument will be a lambda function that converts its argument into uppercase format. As iterable we will pass our list.

map(lambda x: x.upper(), countries)

Shall we try to execute it?

>>> map(lambda x: x.upper(), countries)
<map object at 0x101477890>

We get back a map object. How can we get a list back instead?

We can cast the map object to a list…

>>> list(map(lambda x: x.upper(), countries))
['ITALY', 'UNITED KINGDOM', 'GERMANY']

It’s obvious how using map and lambda makes this code a lot more concise compared to the one where we have use the for loop.

Use Lambda Functions with a Dictionary

I want to try to use a lambda function to extract a specific field from a list of dictionaries.

This is something that can be applied in many scenarios.

Here is my list of dictionaries:

people = [{'firstname':'John', 'lastname':'Ross'}, {'firstname':'Mark', 'lastname':'Green'}]

Once again I can use the map built-in function together with a lambda function.

The lambda function takes one dictionary as argument and returns the value of the firstname key.

lambda x : x['firstname']

The full map expression is:

firstnames = list(map(lambda x : x['firstname'], people))

Let’s run it:

>>> firstnames = list(map(lambda x : x['firstname'], people))
>>> print(firstnames)
['John', 'Mark']

Very powerful!

Passing a Lambda to the Filter Built-in Function

Another Python built-in function that you can use together with lambdas is the filter function.

Below you can see its syntax that requires a function and a single iterable:

filter(function, iterable)

The idea here is to create an expression that given a list returns a new list whose elements match a specific condition defined by a lambda function.

For example, given a list of numbers I want to return a list that only includes the negative ones.

Here is the lambda function we will use:

lambda x : x < 0

Let’s try to execute this lambda passing a couple of numbers to it so it’s clear what the lambda returns.

>>> (lambda x : x < 0)(-1)
True
>>> (lambda x : x < 0)(3)
False

Our lambda returns a boolean:

  • True if the argument is negative.
  • False if the argument is positive.

Now, let’s apply this lambda to a filter function:

>>> numbers = [1, 3, -1, -4, -5, -35, 67]
>>> negative_numbers = list(filter(lambda x : x < 0, numbers))
>>> print(negative_numbers)
[-1, -4, -5, -35]

We get back the result expected, a list that contains all the negative numbers.

Can you see the difference compared to the map function?

The filter function returns a list that contains a subset of the elements in the initial list.

How Can Reduce and Lambda Be Used with a List

Another common Python built-in function is the reduce function that belongs to the functools module.

reduce(function, iterable[, initializer])

In this example we will ignore the initialiser, you can find more details about it here.

What does the reduce function do?

Given a list of values:

 [v1, v2, ..., vn]

It applies the function passed as argument, to the first two elements of the iterable. The result is:

[func(v1,v2), v3, ..., vn]

Then it applies the function to the result of the previous iteration and the next element in the list:

[func(func(v1,v2),v3), v4, ..., vn]

This process continues left to right until the last element in the list is reached. The final result is a single number.

To understand it in practice, we will apply a simple lambda that calculates the sum of two numbers to a list of numbers:

>>> reduce(lambda x,y: x+y, [3, 7, 10, 12, 5])
37

Here is how the result is calculated:

((((3+7)+10)+12)+5)

Does it make sense?

Let’s see if we can also use the reduce function to concatenate strings in a list:

>>> reduce(lambda x,y: x + ' ' + y, ['This', 'is', 'a', 'tutorial', 'about', 'Python', 'lambdas'])
'This is a tutorial about Python lambdas'

It works!

Lambda Functions Applied to a Class

Considering that lambdas can be used to replace regular Python functions, can we use lambdas as class methods?

Let’s find out!

I will define a class called Gorilla that contains a constructor and the run method that prints a message:

class Gorilla:
    def __init__(self, name, age, weight):
        self.name = name
        self.age = age
        self.weight = weight

    def run(self):
        print('{} starts running!'.format(self.name))

Then I create an instance of this class called Spartacus and execute the run method on it:

Spartacus = Gorilla('Spartacus', 35, 150)
Spartacus.run()

The output is:

Spartacus starts running!

Now, let’s replace the run method with a lambda function:

run = lambda self: print('{} starts running!'.format(self.name))

In the same way we have done in one of the sections above we assign the function object returned by the lambda to the variable run.

Notice also that:

  • We have removed the def keyword because we have replaced the regular function with a lambda.
  • The argument of the lambda is the instance of the class self.

Execute the run method again on the instance of the Gorilla class…

…you will see that the output message is exactly the same.

This shows that we can use lambdas as class methods!

It’s up to you to chose which one you prefer depending on what makes your code easy to maintain and to understand.

Using Lambda with the Sorted Function

The sorted built-in function returns a sorted list from an iterable.

Let’s see a simple example, we will sort a list that contains the names of some planets:

>>> planets = ['saturn', 'earth', 'mars', 'jupiter']
>>> sorted(planets)
['earth', 'jupiter', 'mars', 'saturn']

As you can see the sorted function orders the list alphabetically.

Now, let’s say we want to order the list based on a different criteria, for example the length of each word.

To do that we can use the additional parameter key that allows to provide a function that is applied to each element before making any comparison.

>>> sorted(planets, key=len)
['mars', 'earth', 'saturn', 'jupiter']

In this case we have used the len() built-in function, that’s why the planets are sorted from the shortest to the longest.

So, where do lambdas fit in all this?

Lambdas are functions and because of this they can be used with the key parameter.

For example, let’s say I want to sort my list based on the third letter of each planet.

Here is how we do it…

>>> sorted(planets, key=lambda p: p[2])
['jupiter', 'earth', 'mars', 'saturn']

And what if I want to sort a list of dictionaries based on the value of a specific attribute?

>>> people = [{'firstname':'John', 'lastname':'Ross'}, {'firstname':'Mark', 'lastname':'Green'}]
>>> sorted(people, key=lambda x: x['lastname'])
[{'firstname': 'Mark', 'lastname': 'Green'}, {'firstname': 'John', 'lastname': 'Ross'}]

In this example we have sorted the list of dictionaries based on the value of the lastname key.

Give it a try!

Python Lambda and Error Handling

In the section in which we have looked at the difference between lambdas and regular functions, we have seen the following:

>>> multiply
<function multiply at 0x101451d40>
>>> multiply_lambda
<function <lambda> at 0x1014227a0>

Where multiply was a regular function and multiply_lambda was a lambda function.

As you can see the function object for a regular function is identified with a name, while the lambda function object is identified by a generic <lambda> name.

This also makes error handling a bit more tricky with lambda functions because Python tracebacks don’t include the name of the function in which an error occurs.

Let’s create a regular function and pass to it arguments that would cause the Python interpreter to raise an exception:

def calculate_sum(x, y):
    return x+y

print(calculate_sum(5, 'Not_a_number'))

When I run this code in the Python shell I get the following error:

>>> def calculate_sum(x, y):
...     return x+y
... 
>>> print(calculate_sum(5, 'Not_a_number'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in calculate_sum
TypeError: unsupported operand type(s) for +: 'int' and 'str'

From the traceback we can clearly see that the error occurs at line 2 of the calculate_sum function.

Now, let’s replace this function with a lambda:

calculate_sum = lambda x, y: x+y
print(calculate_sum(5, 'Not_a_number'))

The output is:

>>> calculate_sum = lambda x,y: x+y
>>> print(calculate_sum(5, 'Not_a_number'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

The type of exception and the error message are the same, but this time the traceback tells us that there was an error at line 1 of the function <lambda>.

Not very useful!

Imagine if you had to find the right line among 10,000 lines of code.

Here is another reason for using regular functions instead of lambda functions when possible.

Passing a Variable List of Arguments to a Python Lambda

In this section we will see how to provide a variable list of arguments to a Python lambda.

To pass a variable number of arguments to a lambda we can use *args in the same way we do with a regular function:

(lambda *args: max(args))(5, 3, 4, 10, 24)

When we run it we get the maximum between the arguments passed to the lambda:

>>> (lambda *args: max(args))(5, 3, 4, 10, 24)
24

We don’t necessarily have to use the keyword args. What’s important is the * before args that in Python represents a variable number of arguments.

Let’s confirm if that’s the case by replacing args with numbers:

>>> (lambda *numbers: max(numbers))(5, 3, 4, 10, 24)
24

Still working!

More Examples of Lambda Functions

Before completing this tutorial let’s have a look at few more examples of lambdas.

These examples should give you some more ideas if you want to use lambdas in your Python programs.

Given a list of Linux commands return only the ones that start with the letter ‘c’:

>>> commands = ['ls', 'cat', 'find', 'echo', 'top', 'curl']
>>> list(filter(lambda cmd: cmd.startswith('c'), commands))
['cat', 'curl']

From a comma separated string with spaces return a list that contains each word in the string without spaces:

>>> weekdays = "monday   , tuesday, wednesday,thursday,   friday,  saturday  ,sunday"
>>> list(map(lambda word: word.strip(), weekdays.split(',')))
['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']

Generate a list of numbers with the Python range function and return the numbers greater than four:

>>> list(filter(lambda x: x > 4, range(15)))
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

Conclusion

In this tutorial we have seen what a Python lambda is, how to define it and execute it.

We went through examples with one or more arguments and we have also seen how a lambda returns a function object (without the need of a return statement).

Now you know that a lambda is also called an anonymous function because when you define it you don’t bind it to a name.

Also, analysing the difference between regular functions and lambda functions in Python has helped us understand better how lambdas works.

It’s very common to use lambda functions when they are needed only once in your code. If you need a function that gets called multiple times in your codebase using regular functions is a better approach to avoid code duplication.

Always remember how important is to write clean code, code that anyone can quickly understand in case of bugs that need to be fixed quickly in the future.

Now you have a choice between lambdas and regular functions, make the right one! 🙂

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *