Anonymous Functions: Lambda¶
The lambda
keyword is a way to create a function on the fly, without giving it a name. Hence the term “anonymous” – it has no name.
Using lambda
¶
Structure¶
“lambda” is a keyword – it can not be used as a variable name, etc. A lambda expression looks like:
lambda <parameters> : <expression>
It is an expression – which means it evaluates to a value – which means that it can be assigned to a variable, put in a container (such as a list or dict) etc.
The parameters are just like function parameters – but without the parentheses. And they exist in the local scope of the lambda, and can thus be used in the expression.
The expression can be any expression using global variables or the parameters – but not a statement – anyone remember what the difference is?
An expression is something that evaluates to a value, and can be assigned to a variable etc. but things like for
and while
loops and if...else
structures are NOT expressions, and thus can’t be put in a lambda.
In short, lambda is only for very simple functions with no real flow control.
Example¶
In [1]: f = lambda x, y: x + y
In [2]: f(3,4)
Out[2]: 7
This creates a function that takes two positional parameters, x
and y
, and returns their sum.
This is ALMOST the same as:
In [3]: def f2(x, y):
...: return x + y
In [4]: f2(3,4)
Out[4]: 7
So what is the difference? Well, lambda
creates an “anonymous” function – it doesn’t have a name:
In [10]: f.__name__
Out[10]: '<lambda>'
All lambda functions are called <lambda>. But:
In [11]: f2.__name__
Out[11]: 'f2'
Regular “def” defined functions know their name.
So lambda
creates a function, but it doesn’t have a name, and it can only have a single expression in it – no flow control.
What’s the point?¶
There is nothing you can do with lambda that you can’t do with regular def
functions. But there are times when you just need a simple quick function that you don’t need to keep around or refer to again – so it’s a handy syntax for these situations.
A sorting key function is a great example:
In [55]: lst = [("Chris","Barker"), ("Fred", "Jones"), ("Zola", "Adams")]
In [56]: lst.sort()
In [57]: lst
Out[57]: [('Chris', 'Barker'), ('Fred', 'Jones'), ('Zola', 'Adams')]
Tuples are sorted, be default, by their first element. But what if you wanted to sort by the second (index 1) element – last name in this case:
In [13]: def sort_key(item):
...: return item[1]
...:
In [14]: lst.sort(key=sort_key)
In [15]: lst
Out[15]: [('Zola', 'Adams'), ('Chris', 'Barker'), ('Fred', 'Jones')]
straightforward enough. But kind a lot of extra code, eh? and now there is this function: “sort_key” hanging around. You could delete it: del sort_key
, but that would be even more code.
But with a lambda, you simply define it inline:
In [16]: lst = [("Chris","Barker"), ("Fred", "Jones"), ("Zola", "Adams")]
In [17]: lst.sort(key=lambda x: x[1])
In [18]: lst
Out[18]: [('Zola', 'Adams'), ('Chris', 'Barker'), ('Fred', 'Jones')]
Nice and compact and clear, with no extra names hanging around.
You’ll find them useful with things like map
, filter
, and reduce
. as well.
Functions as first class objects¶
lambda functions are python objects; they can be stored in a list or other container:
In [7]: l = [lambda x, y: x+y]
In [8]: type(l[0])
Out[8]: function
And you can call it by indexing the container:
In [9]: l[0](3,4)
Out[9]: 7
You can do that with “regular” functions too:
In [12]: def fun(x,y):
....: return x+y
....:
In [13]: l = [fun]
In [14]: type(l[0])
Out[14]: function
In [15]: l[0](3,4)
Out[15]: 7
If the goal is to have that little function in the list, and you don’t need to give it a name and/or reference it anywhere else, then lambda is a cleaner way to do it.
lambda and keyword arguments¶
lambda functions can take keyword arguments as well:
In [20]: (lambda x=None: x * 2)(x=4)
Out[20]: 8
Remember that default arguments get evaluated when the function is defined. This is the case with lambda as well. This can get you in trouble if you use a mutable in a function definition. But it also can be a handy way to “bake in” a value into a function to be used later:
In [186]: l = []
In [187]: for i in range(3):
l.append(lambda x, e=i: x**e)
This creates a list, in this case with three items. Each of those items is a function. Note that the lambda is called each time through the loop, so each one has that default parameter defined separately – and each time the default is set to the current value of i
in the loop. So we get three functions, all the same except for the default value of e
– that is, each function will raise the input value to a different power.
We can loop through that list, and call each function in turn with the same input value:
In [25]: for f in func_list:
...: print(f(2))
...:
1
2
4
8
and presto! 2 raised to the zeroth, then first, the second, … power.
This may seem pretty obscure, but it’s a handy way to auto-generate custom functions on the fly – like for GUI callbacks, for instance:
https://wiki.wxpython.org/Passing%20Arguments%20to%20Callbacks