Python lambda function - with simple examples

Introduction to Python lambda

In Python and other programming languages, Lambda expressions have their roots in lambda calculus. Which was invented by Alozno Church. Lambda in Python are little anonymous functions, subject to a more restrictive but more concise syntax than regular Python functions. In this tutorial we will learn about python lambda functions and how they are related to regular functions. Moreover, we will also cover how to write lambda functions and how to use it properly.

 

Python lambda as Anonymous function

  • The lambda keyword creates an anonymous function within a Python expression.
  • However, the simple syntax of Python limits the body of lambda functions to be pure expressions.
  • In other words, the body cannot contain other Python statements such as whiletry, etc. Assignment with = is also a statement, so it cannot occur in a lambda.
  • The new assignment expression syntax using := can be used, but if you need it, your lambda is probably too complicated and hard to read, and it should be refactored into a regular function using def.

 

Problems with Anonymous Functions

  • Beyond the Python-specific syntax constraints, anonymous functions have a serious drawback in any language.
  • Stack traces are easier to read when functions have names.
  • Anonymous functions are a handy shortcut, people have fun coding with them, but sometimes they get carried away—especially if the language and environment encourage deep nesting of anonymous functions, like JavaScript on Node.js do.
  • Lots of nested anonymous functions make debugging and error handling hard.
  • Asynchronous programming in Python is more structured, perhaps because the limited lambda syntax prevents its abuse and forces a more explicit approach.

 

Syntax of Python lambda function

A lambda expression creates a function object just like the def statement. Here is the syntax used to define a function using lambda:

Advertisement
lambda argument: argument

Notice that we didn’t define a name to function , we just used keyword lambda and passed argument.

As already informed python lambda function only contains expressions and does not contain statements in the body. Statements like return, pass, assert, or raise will raise a syntaxError exception.

See the example below which raises a  syntax error when we try to use return in lambda.

Python lambda function - with simple examples

In contrast to a normal function, a Python lambda function is a single expression. Although, in the body of a lambda, you can spread the expression over several lines using parentheses or a multi-line string, it remains a single expression. See example below.

#lambda funtion in more than one line
#check even and odd number
number = (lambda x:
(x % 2 and 'odd' or 'even'))(3)

#printing
print(number)

Output:

odd

The example above returns odd when the argument is odd and returns even when we provide an even number as an argument. Although the code contains multiple lines, it still is counted as a single expression.

Advertisement

 

How to use Python lambda function

Here we will first take some examples of python functions and then will convert those into lambda functions. Let us start working with lambda by taking identity functions. Identity functions are those functions that return their arguments.

A very simple identity function is Python will be:

def main(argument):
   return argument

This function returns its argument whenever you call it. Now let us try to convert the same function in Lambda. See the python function which returns the square of the number.

def main(argument):
   return argument*argument

If we try to write the same function in lambda, it will be something like this.

lambda argument: argument*argument

Moreover, we can also store the return value of lambda function in a variable  and later use that name to get access to the return value. See the example below which similar to the above example.

square = lambda argument: argument*argument

As in the definition we said that lambda can take multiple arguments. Let us now take an example to see how multiple arguments in lambda works.

# defining lambda function with multiple arguments
Multiply = lambda num1, num2: num1*num2

# printing the function
print(Multiply(2, 3))

Output:

6

Notice that multiple arguments in lambda are not inside any parentheses, they are just separated by commas.

Advertisement

We can pass arguments to the lambda function, immediately after defining it in the same line. See example below;

# defining lambda function and passing arguments
square = (lambda num1, num2: num1*num2)(2, 4)

#printing the function
print(square)

Output:

8

 

Compare Python lambda vs Python functions

You might wonder what is the main thing that differentiate between lambda and other python functions. Now in this section let us see how Python sees a function with a return single return statement and a lambda function.

First we have to import a python module named dis which exposes functions to analyse Python bytecode generated by the Python compiler.

import dis

# defining function
def main(argument):

   # Return argument
   return argument*argument

#printing the type
print(type(main))

#printing name
print(main)

Output:

<class 'function'>
<function main at 0x7f3ab5f7c1f0>

Now we define the same logic using lambda function:

# Importing dis module
import dis

# defining lambda function and passing arguments
square = lambda num1, num2: num1*num2

# printing the typeof square defined above
print(type(square))

# printing name
print(square)

Output:

<class 'function'>
<function <lambda> at 0x7f8b5005d1f0>

The bytecode interpreted by Python is the same for both functions. But you may notice that the naming is different: the function name is main for a function defined with def, whereas the Python lambda function is seen as lambda.

Advertisement

 

Passing arguments in python lambda

Like a normal function, lambda allows us to pass arguments in many ways. We can pass positional arguments, named arguments, variable lists, and keyword arguments as well.

 

Example-1: Pass arguments to lambda function

See the following examples to get familiar with different ways to pass arguments.

#passing arguments in lambda
number = (lambda a, b: a + b)(1, 3)

#printing
print(number)

Output:

4

 

Example-2: Define variables inside lambda function

we can also define variables inside the lambda. See the example below where we defined variable b and equalize it to 3.

#passing arguments in lambda
number = (lambda a, b=3: a + b)(1)

#printing
print(number)

Output:

4

 

Example-3: Perform operation on the arguments

lambda also allows us to take as many arguments and return a function. See the example below where sum() function is returned.

#passing arguments in lambda
number = (lambda *args: sum(args))(2,2,2)

#printing
print(number)

Output:

6

 

Example-4: Handle return in lambda function

Moreover, we can take defined variable values as argument and return through a function as a return statement. See the example below.

#passing arguments in lambda
number = (lambda **kwargs: sum(kwargs.values()))(a=2, b=2, c=3)

#printing
print(number)

Output:

7

 

Closure function in lambda

A closure function is a nested function which has access to a free variable from an encoding function that has finished its execution. There are mainly three main characteristics of closure function in Python.

  • First, it is a nested function.
  • Second, it has access to a free variable (a variable that is not bound in the local scope)  in outer space
  • Tthird characteristic is it is returned from the enclosing function.

The concepts of lambdas and closures are not necessarily related, although lambda functions can be closures in the same way that normal functions can also be closures. Here is an example of a closure function in python.

# This is the outer enclosing function
def message(msg):

   # This is the nested function
   def printer():

       #printing
       print(msg)

   return printer  # returns the nested function

# Now let's try calling this function.
another_message = message("Hello")
another_message()

Output:

Hello

In a similar way lambda can also be used as a closure function. See the example below:

## This is the outer enclosing function
def message():

    # This is the nested function
   return lambda : "Hello"

closure = message()
print(closure())

Output:

Hello

 

Evaluation time of lambda

Sometimes using lambda in a loop can behave unexpectedly. The following examples demonstrate the difference when using a regular function vs using a Python lambda. Let first take a regular function as an example.

def main(x):

   # Nested function
   def f():
       print(x)
   return f

num = 'first', 'second', 'third'

# creating empty list
fun = []

for x in num:
   fun.append(main(x))

for f in fun:
   # calling nested function
   f()

Output:

first
second
third

In a normal function, x is evaluated at definition time, when the function is added to the list: fun.append(main(x)).

Now, let us implement the same logic in lambda.

num = 'first', 'second', 'third'

# creating empty list
fun = []

# for loop
for x in num:
   fun.append(lambda: print(x))

# calling the f() using loop
for f in fun:
  f()

Output:

third
third
third

The unexpected result occurs because the free variable x, as implemented, is bound at the execution time of the lambda expression. The Python lambda function is a closure that captures x, a free variable bound at runtime. At runtime, while invoking the function f() the value of x is three.

We can overcome this issue by free variable at definition time. See the example below.

num = 'first', 'second', 'third'

# creating empty list
fun = []

# for loop
for x in num:
   fun.append(lambda x=x: print(x))

# calling the f() using loop
for f in fun:
  f()

Output:

first
second
third

 

When to avoid using Python lambda function

In some cases we might face problems while using lambda. So, in such cases using a regular function would be the best option. In the following section, we will see some examples where the use of  lambda should be avoided.

 

Raising an exception in lambda

If we want to raise an exception, we should avoid using it with lambda. Rather using a regular function for exception handling will be the best option. See the following example, which gives you an error if you want to raise an exception with lambda.

Python lambda function - with simple examples

 

Python class and lambda

We can use lambda to write methods in Python but we should avoid using it. See the example below, which is legal Python code but exhibits unconventional python code relying on lambda. For example, instead of implementing __str__ as a regular function, it uses a lambda. Similarly, brand and year are properties also implemented with lambda functions, instead of regular functions or decorators:

# Python class
class Person:
   """Person information using lambda."""

   def init__(self, name, age):
       self.name = name
       self.age = age

       # using lambda instead of def
       name = property(lambda self: getattr(self, '_name'),
                    lambda self, value: setattr(self, '_name', value))

   # Using lambda instead of def
   age = property(lambda self: getattr(self, '_age'),
                   lambda self, value: setattr(self, '_age', value))

   str__ = lambda self: f'{self.name} {self.age}'
   BA = lambda self: print('BA!')

This code gives error error E731. We should avoid using lambda in python class and instead should use def.

 

Usage of Python Lambda

In the functional programming paradigm, some of the best known higher-order functions are mapfilterreduce, and apply.

The apply function was deprecated in Python 2.3 and removed in Python 3 because it’s no longer necessary. If you need to call a function with a dynamic set of arguments, you can write fn(*args, **kwargs) instead of apply(fn, args, kwargs).

The mapfilter, and reduce higher-order functions are still around, but better alternatives are available for most of their use cases, as the next section shows.

 

Replacement of filter() function

The filter() is a python built-in function that takes a predicate as a first argument and an iterable as a second argument. It builds an iterator containing all the elements of the initial collection that satisfies the predicate function.

Here we try to find a list of factorials of odd numbers up to 5!, using both map and filter.

>>> list(map(factorial, filter(lambda n: n % 2, range(6)))) 
[1, 6, 120]

List comprehension does the same job, replacing map and filter, and making lambda unnecessary.

>>> [factorial(n) for n in range(6) if n % 2] 
[1, 6, 120]
>>>

 

Let us see one more example:

# creating lambda
ODD= lambda x: x%2 != 0

# filtering and storing in list
odd_list = list(filter(ODD, range(11)))

# printing the list
print(odd_list)

Output:

[1, 3, 5, 7, 9]

The same logic can be implemented in another way without using lambda. See the example below.

#printing the list of odd numbers
print([x for x in range(11) if x%2 != 0])

Output:

[1, 3, 5, 7, 9]

 

Replacement of map() function

The map() is a python built-in function that takes a function as the first argument and applies it to each of the elements of its second argument, an iterable. Examples of iterables include strings, lists and tuples. The map() returns an iterator corresponding to the transformed collection. For example, we can use map() to transform a list of strings to a new list with each string capitalized.

# list of names
names = ['bashir', 'alam', 'arylen']

# printing list and capitalizing using lambda
print(list(map(lambda x: x.capitalize(), names)))

Output:

['Bashir', 'Alam', 'Arylen']

Now let's see how we can achieve the same logic without using lambda.

# list of names
names = ['bashir', 'alam', 'arylen']

# printing list and capitalizing without using lambda
print([x.capitalize() for x in names])

Output:

['Bashir', 'Alam', 'Arylen']

 

Summary

Lambda is also known as an anonymous function because of its anonymous behavior. It  can take any number of arguments but only one expression. The expression is evaluated and returned. Lambda functions can be used wherever function objects are required. In this tutorial we learned about lambda, their anonymous behavior and problems that lambda can cause in some cases. Moreover, we also learned about some cases where we should avoid using lambda.

Further Reading

lambda
lambda in python
History of lambda

Didn't find what you were looking for? Perform a quick search across GoLinuxCloud

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

Leave a Comment