Chapters
Python114 chapters

FunctionsChapter 55 of 114

Lambda

A small unnamed function, and when a def is the better choice.

A function in an expression

lambda builds a function without giving it a name:

Python
double = lambda n: n * 2
print(double(5))

Output

10

That is exactly equivalent to:

Python
def double(n):
    return n * 2

print(double(5))

Output

10

Where it belongs

A lambda earns its place as an argument to something else, where naming it would be noise:

Python
people = [("Ada", 36), ("Grace", 45), ("Katherine", 28)]
print(sorted(people, key=lambda person: person[1]))

Output

[('Katherine', 28), ('Ada', 36), ('Grace', 45)]

The function is used once, right there, and a name would not add anything.

Python
words = ["banana", "Apple", "cherry"]
print(sorted(words, key=lambda w: w.lower()))
print(max(words, key=len))

Output

['Apple', 'banana', 'cherry']
banana

The rules

A lambda takes any arguments but its body must be a single expression, whose value is returned automatically:

Python
add = lambda a, b: a + b
greet = lambda name="there": f"Hello, {name}"

print(add(2, 3))
print(greet())
print(greet("Ada"))

Output

5
Hello, there
Hello, Ada

No statements are allowed — no if blocks, no loops, no assignments, no return. A conditional expression is fine, because it is an expression:

Python
label = lambda n: "even" if n % 2 == 0 else "odd"
print(label(4), label(7))

Output

even odd

With map and filter

Python
numbers = [1, 2, 3, 4]
print(list(map(lambda n: n * n, numbers)))
print(list(filter(lambda n: n % 2 == 0, numbers)))

Output

[1, 4, 9, 16]
[2, 4]

Most Python programmers write those as comprehensions, which read left to right and need no lambda at all:

Python
numbers = [1, 2, 3, 4]
print([n * n for n in numbers])
print([n for n in numbers if n % 2 == 0])

Output

[1, 4, 9, 16]
[2, 4]

The late-binding trap

A lambda looks up its enclosing variables when it runs, not when it is made. In a loop, that means every lambda sees the final value:

Python
funcs = [lambda: i for i in range(3)]
print([f() for f in funcs])

Output

[2, 2, 2]

Capture the value with a default argument, which is evaluated at definition time:

Python
funcs = [lambda i=i: i for i in range(3)]
print([f() for f in funcs])

Output

[0, 1, 2]

This is not really about lambdas — a nested def behaves the same way — but this is where people meet it.

operator instead

For the common "get item n" or "add these" cases, operator is clearer than a lambda:

Python
from operator import itemgetter

people = [("Ada", 36), ("Grace", 45)]
print(sorted(people, key=itemgetter(1), reverse=True))

Output

[('Grace', 45), ('Ada', 36)]

Test yourself

2 questions

What can a lambda body contain?

Show the answer

A single expression — No if blocks, loops or assignments. A conditional expression is fine, because it is an expression.

Why does [lambda: i for i in range(3)] give three functions that all return 2?

Show the answer

Each looks up i when it runs, by which time the loop has finished — Capture the value with a default argument, lambda i=i: i, which is evaluated at definition time.

Next chapter

Decorators

Wrap a function to add behaviour, without editing the function.