Python Lambda
The lambdas are anonymous one line functions in Python that can be used to perform tasks which don't require regular Python functions. Some of the most useful features of Python lambdas are...
- Lambda function can take any number of arguments
- Lambda functions are very short although can be very encryptic
- Lambda functions can be used to return function objects
- Lambda functions are restricted to only a single expression
Below snippet shows the basic syntax of a Python function. The below function takes "argument" and returns it back.
# normal function that returns a valuedeffunctionName(argument):returnargumentLambda Function Definion
Example of above function "functionName" using Lambda
lambdaargument:argumentNote the syntax of the above function. Lambda functions have no name. They are defined and used on the fly. We can't reuse them in the form defined above. The first 'argument' is the argument of the function and the 2nd 'argument' is the returned value.
Example: - Lambda function that returns the twice of the given input.
lambdax:x*2But you must be wondering, how to provide the input to above lambda function!
Calling the Lambda Function
To use the function, you can surround it with parenthesis and provide the parameters between paranthesis as shown below.
(lambdax:x*2)(5)This is how it works...
# (lambda x: x * 2 )(5) = lambda 5 : 5 * 2 = 5 * 2 = 10There is another way to provide an argument to the lambda function. We can assign the lambda function to a variable and then pass the argument to that variable as shown below...
double=lambdax:x*2# and call it like so : double(5)Ofcourse above lambda function and below function are equivalent.
# the function double is equivalent to : defdouble(x):returnx*2Lambda Functions With Mutiple Arguments
Python Lambda functions can have multipe parameters separated by commas (,) here is an example...
pairs=lambdax,y:"P( x = "+str(x)+" , y = "+str(y)+" )"pairs(1,2)There is a shorthand way of calling Python lambdas function that is without assigning a name to the function.
You can simply do this :
lambdaa,b:a*bThere will be no conflict and you can call the above lambda function with the arguments like this...
_(2,3)Note the underscore in the above syntax. Underscore refers to the lambda function that we just described above.
Ofcourse, you can use IIFE ( Immediately Invoked Function Expression ) syntax too.
(lambdaa,b:a*b)(2,3)We can use function inside lambda. Below snippet is an example of lambda function inside another lambda function.
# we can use a function as a parameter of lambda : myfunction=lambdaparam,func:param+func(param)# and call it like so : myfunction(3,lambdax:x**2)In the above snippet, we passed outer lambda function two parameters - param and another lambda function (func)
myfunction(4,lambdax:x-1)importdisdiv=lambdax,y:x/ytype(div)dis.dis(div)div# applaying same thing for a normal function: importdisdefdiv(x,y):returnx/ytype(div)dis.dis(div)divLambda functions throws similar errors as Python regular functions do. For example, below snippet will throw string multiplication error "can't multiply sequence by non-int of type 'str'"
type_error=lambdastr1,str2:str1*str2type_error("hello","world")We can't add statments in lambda function as shown below.
(lambdax:assertx>0)(1)However we can use parenthesis to achieve the statement effect.
In below snippet, note expression (x>0 and + or '-') would translate to if x > 0 then return '+' otherwise return '-'
(lambdax:(x>0and'+'or'-'))(-5)Hinting doesn't work on lambda functions. It only works on normal functions.
Below regular Python function takes 'string' and 'integer' as two parameters but returns output as string.
deffunction(param:str,i:int)->str:returnparam*str(i)In lambda function, if you specify type hints, you will end up getting a syntaxError...
lambdaparam:str,i:int:param*i*args and **kwargs in Python Lambda
As we described above in the 'multiple arguments section' of this post, Python lambda function can take multiple arguments but lambda functions can also take arguments using *arg and **kwargs
(lambdap1,p2,p3:(p1+p2+p3)/3)(1,2,3)(lambdap1,p2,p3=3:(p1+p2+p3)/3)(1,2)*args example
(lambda*args:sum(args)/len(args))(1,2,3)**kwargs example
(lambda**kwargs:sum(kwargs.values())/len(kwargs))(one=1,two=2,three=3)Python lambdas initialize arguments example
(lambdap1,p2=0,p3=0:(p1+p2+p3)/3)(1,p2=2,p3=3)Let us see first, how decorators in regular Python functions work. Here is an example...
# Defining a decoratordeftrace(f):defwrap(*args,**kwargs):print(f"[TRACE] function name: {f.__name__}, arguments: {args}, kwargs: {kwargs}")returnf(*args,**kwargs)returnwrap# Applying decorator to a function@tracedefdouble(x):returnx*2# Calling the decorated functiondouble(3)Check out below example of application of decorator to a lambda function. Notice in the below snippet, how we have wrapped the lambda function inside the trace decorator function. Order of brackets is very important.
print((trace(lambdax:x*2))(3))Lambda is regularly used with built-in functions like map or filter.
map iterates the function through a list or set. The function could be regular Python function or lambda function.
In the below example,lambda function x: x + 5 is applied on list of numbers (0,4)
list(map(lambdax:x+5,range(5)))In the below example,lambda function x: x > 0 is applied on list of numbers [-5,-2,1,0,3,5]
list(filter(lambdax:x>0,[-5,-2,1,0,3,5]))In below snippet, map() is taking two arguments. The first one is the decorator function around lambda function i.e.
trace(lambda x: x * 2) and second argument is range(3).
The map() will run the decorated lambda function 3 times as shown below.
list(map(trace(lambdax:x*2),range(3)))importunittestdouble=lambdax:x*2classTest(unittest.TestCase):deftest_1(self):self.assertEqual(double(1),2)deftest_2(self):self.assertEqual(double(2),4)deftest_10(self):self.assertEqual(double(10),11)# this test will failif__name__=='__main__':unittest.main(verbosity=2)double=lambdax:x*2double.__doc__="""Doubles the number entred in the parameters :>>> double(1)2>>> double(2.0)4.0>>> double(10)20"""if__name__=='__main__':importdoctestdoctest.testmod(verbose=True)Here is how regular Python function raises exception.
defthrow(excep):raiseexcepHere is how lambda functions can raise exception.
(lambda:throw(Exception("my error")))()Let us look at below example. In here (lambda : * 2) _ refers to a variable or parameter.
(lambda_:_*2)(11)Let us take at following more cryptic code example. In below code, there are two Python lambda functions. The parameter _ is being used inside both lambda functions.
(lambda_:list(map(lambda_:_*2,_)))(range(11))# the underscore (_) is the variable # to simplify, the function should be like this : (lambdamyList:list(map(lambdaelement:element*2,myList)))(range(11))Here is how it works.
lambda 0 : list(map(lambda : *2,0)) \ lambda 0 : list(0) \ 0
lambda 1: list(map(lambda : *2, 1)) \ lambda 1: list(2) \ 2 \ ....
Here is the above code in a regular Pythonic way...
# regular functions will make it easy due to their multiline formatdefdoubleItems(myList):double=lambdax:x*2returnmap(double,myList)list(doubleItems(range(11)))# let's sort a list of strings that have a char a space and an int based ont he value of the integermyList=["a 1","b 45","x 11","r 16"]print(sorted(myList))print(sorted(myList,key=lambdax:int(x[2:])))fromtimeitimporttimeittimeit(lambda:sum(range(99999)),number=10)# this silution is cleaner and more readable