When I say “Call a plumber”, you need to know the meaning of “plumber” and “call”, and enough English syntax to be able to execute the command. In case you know what “call” means but not “plumber”, you consult a dictionary before you are ready to execute the command. I could have also said “Call someone who installs, repairs, and maintains piping, fittings, and fixtures involved in the distribution and use of water in a building”, substituting the Merriam-Webster definition of “plumber” for the word itself. This would save you the dictionary lookup.

Let’s define a function fmax(x,y,f) which picks x or y according for which f returns the larger value:

def fmax(x,y,f):
  """Return x, if f(x) > f(y), else, return y"""
  if f(x) > f(y):
    return x
  else:
    return y

And now assume you somehow needed to call fmax – you never know – and the function at your hand is \(f(x)=x^2 - 2x + 1\). The “plumber” way is to first define your function:

def hard_to_name(x):
  return x*x - 2*x + 1

and then call fmax passing the name of your function as the third parameter:

>>> fmax(0.001, 0.9, hard_to_name)
0.001

The Merriam-Webster way on the other hand is passing a “name” that tells what the function does:

>>> fmax(0.001, 0.9, lambda x: x*x - 2*x + 1)
0.001

Here is how def and lambda are related:

def <function_name>(<arg_1>,...,<arg_n>):
    return <expression> 

is equivalent to

lambda <arg_1>,...,<arg_n>: <expression>

in the sense that in any program, wherever you can have <function_name>, you can have lambda <arg_1>,...,<arg_n>: <expression> instead, without changing anything in the behavior of the program. In defining a function with lambda we by-pass the naming step, or from a more illuminating angle, the definition itself becomes the name.1

So far in our programming tasks, when we needed small functions like adding 1 to its argument, checking whether the argument is negative, etc., we were defining these functions by def under a name, and using these names in higher order calls like in proc_seq. From now on, we will instead use lambda functions in such cases. For instance when you want to pass to proc_seq an update function that updates the store by adding the square of the current value, you will not need to define it by def, but rather will pass lambda store, x: store + x*x as the update argument. lambda functions are marvels of convenience in this sense, they save you from naming small functions with very local use, and saves the reader from the burden of searching the definition of the function, as s/he already has the definition in front of his/her eyes.

Besides passing them as arguments to other functions, you can also apply lambda functions to their arguments as you do with defed functions. For instance, you can have:

>>> (lambda x: x + 2)(2)
4
>>> (lambda x, y: x + y)(2,3)
5

You can assign them to names:

>>> f = lambda x: x+2
>>> f
<function <lambda> at 0x104915a60>
>>> f(3)
5

and just like names of a defed function, lambda functions are expressions that evaluate to the function itself:

>>> lambda x: x+2
<function <lambda> at 0x1049159d0>

By this last token, we will use the term “lambda expression” instead of “lambda function”, to emphasize that they are expressions that evaluate to functions.


As you might have noticed from the equivalence above, lambda expressions differ from defed functions not only in lacking explicit names. They also have no room for statements. All you can have to the right of = in a lambda expression is just an expression, i.e. a stretch of code that gets evaluated to a value. This restriction means you cannot have if, while, assignment (=), return, etc., statements in a lambda expression.

At this point you may revolt that how can we compute beyond simple arithmetic without having if? How can we make decisions in a lambda expression?

I didn’t say we cannot have if in a lambda expression, I said we cannot have if statements. We can perfectly have if expressions. In schematic form:

<success_expression> if <condition> else <failure_expression>

is an expression that evaluates to <success_expression> if <condition> evaluates to true, and to <failure_expression> otherwise. Here is a lambda expression that defines our fmax above:

lambda x, y, f: x if f(x) > f(y) else y

As we go along, we will see the ways to do without all sorts of statements for looping, assignment, and so on. Statements are toxic to your programs, you need to learn to avoid them as much as possible. Lambda is a good tool for learning this art. A healthy function is the one that can be written as a lambda expression. You do not have to write your functions as lambda expressions all the time, but do your best to ensure that they are writable as such. This is the essence of the “lambda way” of programming.


Church’s Lambda Calculus, where Python’s lambda’s are coming from, is a much deeper subject than we were able to have here. The appreciation of this depth has some prerequisites which we lack for now. So let’s leave it for a future occasion to be tackled by those who are interested in subjects like theory of computation, advanced functional programming, foundations of logic and mathematics, and so on.

  1. Sometimes lambda functions are called anonymous functions in the “unnamed” sense of the word. I rather find taking the definition itself as the “name” more illuminating.