This tutorial explains what is Python Lambda Function, how and when to use it with examples. Also compares Regular and Lambda functions:
Anonymous function, the term commonly used in computer programming, also known as lambda function has been a feature of many programming languages since 1958, originating in the invention of lambda calculus by Alonzo Church.
Today, a good number of programming languages support Anonymous functions or have libraries that have been made to provide support.
What You Will Learn:
- What Is A Lambda Function
- Lambda Function And Regular Functions
- Differences Between Lambda Functions and Regular Functions
- Similarities Between Lambda Functions And Regular Functions
- When To Use Lambda Functions
- When Not To Use Lambda Functions
- Frequently Asked Questions
What Is A Lambda Function
Generally, an anonymous function is a function without a name. In Python, an anonymous function is created with the lambda keyword, hence sometimes referred to as lambda functions, lambda expressions, etc. In other programming languages, they are called differently.
Suggested reading =>> Lambdas in C++
Programming languages and how their anonymous functions are named.
|Ruby, Smalltalk, C, C++||Blocks|
In Python, a lambda function has a simple syntax, but unlike other supported languages like Haskell, is limited to only a single pure expression in its body. Meaning, it can’t make assignments or use statements like while, for, raise, return, assert, etc.
This doesn’t come as a surprise because originally, Python doesn’t allow statements in its expressions, and lambda is an expression.
Although many Python enthusiasts proposed that Python lambda functions be enhanced to support statements, and others think it’s useless since regular functions are already there for such complexity.
A lambda function has the following syntax:
lambda arg1[, arg2,...,argN] : expression
As seen in the syntax above, a lambda function can have many parameters (separated by a comma and no parentheses) but only a single valid Python expression which is evaluated and returned without the explicit use of the return statement, which by the way is not supported.
NB: The square bracket indicates that the other arguments are optional.
Let’s look at some examples using the Python interactive shell.
Example 1: Define a lambda function that adds up two values.
>>> (lambda a,b: a+b)(2,4) # apply the function immediately 6 >>> add = lambda a,b: a+b # assign the function to a variable >>> add(2,4) # execute the function 6
NB: We should note the following:
- Applying a function immediately is known as IIFE which stands for Immediately Invoked Function Execution.
- Assigning a lambda function to a variable is a bad practice (more on this later).
The above code has the following parts.
As seen in the above figure, the lambda keyword creates the lambda expression. Two parameters are defined and receive any two arguments and pass them to the single python expression defined after the colon(:).
Arguments In Lambda Functions
When it comes to arguments, there is no difference between lambda functions and a regular function. Lambda functions support all the ways of passing arguments supported by regular functions. Check out Python Functions to know more about Function’s arguments.
Example 2: Define lambda functions with the different ways of passing arguments.
>>> (lambda a,b,c=2: a+b+c)(2,3,5) # positional and default parameters 10 >>> (lambda a,*args: a + sum(args))(3,4,2,7,8) # positional and arbitrary positional parameter 24 >>> (lambda **kwargs: sum(kwargs.values()))(a=3,b=9,c=8) # arbitrary keyword parameter 20 >>> (lambda a, *, b: a+b)(3,b=9) # positional and keyword-only parameter 12
Lambda Function And Regular Functions
To recap, lambda functions are functions with no names and are sometimes called anonymous functions, lambda expressions.
In this section, we will look at some similarities and differences between lambda functions and regular functions (functions defined with the def keyword).
Differences Between Lambda Functions and Regular Functions
Differences between Lambda Function and Regular Function.
|Lambda Function||Regular Function|
|It is created using the lambda keyword.||It is created using the def keyword.|
|Traceback identifies a lambda functions as ||Traceback identifies a regular function by its name.|
|Commonly written as a single-line code.||Can contain multiple-line code.|
|Can be invoked immediately(IIFE).||Can't be invoked immediately.|
|Is not bound to a name.||It is bound to a name.|
|Do not support annotations.||Supports annotations.|
|Must have only one expression.||May have multiple expressions.|
|Doesn't support statements.||Supports statements.|
|Must not contain a return statement, but returns its body automatically.||Must contain a return statement in order to return a value. Returns None if no return statement is present.|
The table above summarizes the differences between a lambda and a regular function. However, we shall elaborate more on those points in this section.
#1) Differences In Keywords
This is one of the basic and important differences. A lambda function is defined using the lambda keyword which is different from a regular function that uses the def keyword.
The lambda keyword creates and returns an object while the def keyword creates and binds the object to the function’s name.
Example 3: Keyword differences between Lambda and Regular functions.
#2) Differences In Tracebacks
One of the reasons why lambda functions are not highly recommended is because of the way traceback identifies them. We shall see that, when an exception gets raised in a lambda function, the traceback will identify it as <lambda>. This can be hard to debug as it’ll be difficult to locate the specific lambda function in question.
Traceback identifies regular functions differently and more appropriately by name. This makes them highly favored during debugging.
Example 4: Trigger the ZeroDivisionError exception and see how traceback differs in identifying them.
Traceback identification difference between Lambda and Regular functions.
|lambda traceback||def traceback|
|divide = lambda a,b: a/b|
# divide by zero to raise the 'ZeroDivisionError' exception
# divide by zero to raise the 'ZeroDivisionError' exception
#3) Difference In Line-Code
Lambda functions are commonly written as single-line code. However, they can also be expressed in multi-line code using the backslash(/) or parentheses(()).
As for regular functions, they are commonly expressed in a multi-line code but in cases where a single expression or statement is required, they can also be expressed in a single-line code as seen in example 3 above.
Example 5: Define lambda function in a multi-line code.
# express lambda function in a multi-line code using the multiline string backslash(\) multi_line = lambda : \ print('multiple line code') # execute the lambda function multi_line()
However, for clarity, it is recommended that a lambda function be expressed in a single-line code while regular functions are expressed in a multi-line code.
#4) Differences In Invocation
One of the advantages of lambda functions over regular functions is that they can be invoked immediately, also known as Immediately Invoked Function Execution( IIFE). This makes their definitions suitable as arguments to higher-order functions like map(), filter(), etc. Check example 2 above for a few examples.
If we try to apply this to a regular function, a SyntaxError will be raised.
Example 6: Apply IIFE to a regular function.
>>> (def a(): return 4)() File "<stdin>", line 1 (def a(): return 4)() ^ SyntaxError: invalid syntax
#5) Difference In Binding
Since a lambda function is anonymous, it has no name, hence is not bound to a variable. Unlike a regular function that must be given a name during definition. This is one of the reasons why lambda functions are mostly used when reuse is not required.
#6) Differences In Annotation
Function annotations introduced in PEP 3107 enables us to attach metadata to our function’s parameters and return values. Unlike regular functions, lambda functions do not support annotations.
Annotations use colon(:) to attach metadata before any argument and an arrow(->) to set metadata for the return value. This doesn’t make it suitable for lambda functions as they don’t use parentheses to enclose their arguments and only support a single expression.
Check the article on Documenting and Introspecting Python Functions to know more about function annotations.
#7) Differences In Expressions
Unlike regular functions, a lambda function only supports a single expression. Though the lambda function can be expressed in a multi-line code as seen in example 5, and it still remains a single statement.
#8) Differences In Statements
In Python, statements are actions or instructions that can be executed and are mostly made up of reserved keywords like return, raise, if, for. In Python, we can’t have statements inside expressions. This is why a lambda function can’t support statements as it is an expression in itself.
A lambda function doesn’t support a return statement, but automatically returns the result of its expression. A regular function on the other hand requires a return statement in order to return a value. A regular function without a return statement automatically returns None.
Let’s check this claim in the below example.
Example 7: Check the return object of a regular function that has no return statement.
>>> def a(): ... pass # pass statement. Does nothing. ... >>> b = a() # execute our function and assign the return value. >>> b == None # compare to 'None' True
Similarities Between Lambda Functions And Regular Functions
Lambda function is just a function after all. Though they have some differences that we saw above, they also have some similarities. In this section, we shall take a look at some of their similarities.
#1) Execution By The Compiler
In a nutshell, a lambda function and a regular function with a single return statement have the same bytecode generated by the compiler during execution.
As we mentioned above, a lambda function is just a function. We can verify this claim with the built-in type() function as seen below.
>>> add = lambda a, b: a + b >>> type(add) <class 'function'>
To verify the similarities in bytecode, we can use the dis module as seen below.
>>> add = lambda a, b: a + b # define our lambda function >>> def add2(a,b): return a + b # define our regular function ... >>> import dis # import the dis module >>> dis.dis(add) # introspect the lambda function bytecode 1 0 LOAD_FAST 0 (a) 2 LOAD_FAST 1 (b) 4 BINARY_ADD 6 RETURN_VALUE >>> dis.dis(add2) # introspect the regular function bytecode 1 0 LOAD_FAST 0 (a) 2 LOAD_FAST 1 (b) 4 BINARY_ADD 6 RETURN_VALUE >>>
As we saw above, a lambda function is just a function. Hence, it supports the same ways of argument passing as regular functions. Check example 2 that demonstrates arguments in lambda functions.
A decorator is a feature in Python that allows us to add new functionality to an object without tempering with its original structure. This feature is very common in practice, so there is no doubt that a lambda function will support such a feature.
Though it supports decorators, it doesn’t use the @ syntax for decoration, but simply calls the lambda function.
# define our decorator that simply prints the function's name and arguments def print_args(func): def wrap(a, b): print("Arguments for :", func.__name__) print("Args 1: ", a) print("Args 2: ", b) return func(a,b) return wrap # Add decorator to regular function using the @ prefix @print_args def add(a,b): return a + b # Add decorator to lambda function through function call. add2 = print_args(lambda a, b: a + b) if __name__ == "__main__": add(4,5) # execute decorated regular function add2(6,3) # execute decorated lambda function
NB: Though the lambda function is assigned to a variable(bad practice), it is not bound to that variable. Hence, it is identified by <lambda>
A lambda function can be nested because it is just a function. However, it is rare due to its limitations (single expression, no statements, etc).
Whenever a simple single expression is needed, a lambda function can be used rather than binding a variable with the def statement. But still, we recommend using the def statement for readability and debugging purposes.
def enclosing_func(a): # nesting a lambda function return lambda b: a + b if __name__ == "__main__": # execute enclosing function which returns the nested lambda function. add3 = enclosing_func(3) print(add3(32)) print(add3(2))
When To Use Lambda Functions
As stated above, a lambda function is a function without a name. That being said, the most important reason for using lambda functions is when we only need that function once and it only requires a single expression.
Mostly these lambda functions are used in Higher-order built-in functions like map(), filter(), reduce(), sorted(), min(), etc as arguments or key attribute’s value.
Example 12: Sort a list of integers using the sorted() function.
>>> l = [4,5,3,7,9,1] # define our list of integers >>> sorted(l) # sort in ascending order [1, 3, 4, 5, 7, 9] >>> sorted(l, reverse=True) # sort in descending using 'reverse' [9, 7, 5, 4, 3, 1] >>> sorted(l, key=lambda x: -x) # sort in descending using 'key' attribute and lambda [9, 7, 5, 4, 3, 1]
Example 13: Filter out only the odd numbers from a list.
>>> l = [1, 5, 4, 6, 0, 8, 11, 13, 12] >>> list(filter(lambda x: x%2 != 0, l)) [1, 5, 11, 13]
NB: List comprehensions and generator expressions are arguably preferred in many cases. They are more readable and arguably faster.
>>> l = [1, 5, 4, 6, 0, 8, 11, 13, 12] >>> [x for x in l if x%2 != 0] [1, 5, 11, 13]
Note that this doesn’t mean that we can’t use lambda functions in higher-order functions, what we are trying to point out is that listcomps and generator expressions are preferred in many cases.
When Not To Use Lambda Functions
Lambda functions have their limitations and best practices. In this section, we will elaborate on a few.
#1) When Binding Is Required
In the PEP8 Guide, it is recommended to use a def statement instead of assigning a lambda function to a variable. Lambda functions are meant to be used directly and not saved for later usage.
>>> def test(x): return x*2 # Correct ... >>> test(3) 6 >>> t = lambda x: x*2 # Wrong >>> t(3) 6
In order to execute a lambda function immediately, we can use the IIFE as seen in example 1 above.
#2) When Type Annotations Are Required
We may be tempted to apply annotations like in normal functions. However, lambda functions do not support type annotations. If it is required, then we are better off defining our functions with the def statement.
Example 16: Apply type annotations in a lambda function.
>>> lambda x: int: x+2 File "<stdin>", line 1 SyntaxError: illegal target for annotation
As we can see above, a SyntaxError is raised if we try to use type annotations in a lambda function.
#3) When Statements Are Required
We already saw above that lambda functions don’t support statements. It is very common too, for example, to raise exceptions in a function whenever we identify a problem. Unfortunately, a lambda function can’t incorporate a raise statement.
If your function needs to work with statements, then define it with the def statement instead of a lambda statement.
Example 17: Raise an exception in a lambda function.
>>> lambda: raise Exception("Wrong move") File "<stdin>", line 1 lambda: raise Exception("Wrong move") ^ SyntaxError: invalid syntax
Frequently Asked Questions
Q #1) Can Lambda functions support type annotations?
Answer: Unfortunately, lambda functions also known as anonymous functions don’t support type annotations. If type annotation is required, then it is recommended to use the def statement to define a regular function.
Q #2) What type does Lambda return in Python?
Answer: Just like regular functions, the return type of a lambda function depends on what it computes in its body. It could be int, float, data structures(list, tuple, dictionary), and even functions.
Q #3) Do Lambda functions support ‘print’?
Answer: In Python 2, lambda functions don’t support ‘print’ just because it is a statement. However, in Python 3, we no longer have a print statement but a print function. So, the lambda function very much supports ‘print’ in Python 3.
In this tutorial, we looked at lambda functions. We learned that they are also called anonymous functions, lambda expressions, etc.
We differentiated a lambda function from a Python regular function and also saw the similarities between them. Lastly, we examined cases when and when not to use a lambda function.