What are lambda functions, and when should you avoid them?

4 minbeginnerfunctionslambda

Quick Answer

A lambda is an anonymous, single-expression function. lambda x: x * 2 is equivalent to a def with one return statement, but has no name, no statements (only one expression), and no docstring. Use lambdas for short, throwaway callbacks (sorted(key=lambda x: x.name)). Avoid them for anything that needs a name for debugging/tracebacks, has multiple logical steps, or would benefit from a docstring — PEP 8 explicitly recommends def over binding a lambda to a name.

Detailed Answer

What a lambda is

square = lambda x: x * x
# equivalent to:
def square(x):
    return x * x

A lambda is restricted to a single expression — no statements (no if/for blocks, no multiple lines, no assignments other than the walrus operator inside the expression). Its return value is always that one expression's result.

Good uses: short, inline, throwaway callbacks

people.sort(key=lambda p: p.last_name)
sorted(words, key=lambda w: (-len(w), w))
list(filter(lambda x: x % 2 == 0, numbers))
button.on_click(lambda: print("clicked"))

These are idiomatic. The lambda exists only to describe "how to sort/ filter this," used once, right where it's needed. Naming it separately would add indirection without adding clarity.

Why PEP 8 discourages binding a lambda to a name

# PEP 8: don't do this
f = lambda x: x * 2

# do this instead
def f(x):
    return x * 2

Once you're naming the function anyway, def is strictly better:

  • Tracebacks show the real name. A named lambda's __name__ is literally "<lambda>", which makes stack traces harder to read.
  • def supports a docstring, statements, multiple lines, and default values with the same clarity as any other function.
  • No expressiveness advantage — a bound lambda can't do anything a one-line def can't, so there's no upside to the restriction.

Lambdas can't contain statements — a common trip-up

lambda x: print(x); return x   # SyntaxError -- can't have multiple statements
lambda x: x if x > 0 else -x   # OK -- this is a conditional EXPRESSION, not a statement

A conditional expression (a if cond else b) is fine inside a lambda. Actual statements (if, for, try, assignment, return) are not.

Lambdas are single-expression anonymous functions, ideal for short inline callbacks like sort keys or simple filters. The moment a lambda is complex enough to need a name, multiple steps, or a docstring, write a regular def instead. PEP 8 treats name = lambda: ... as an anti-pattern.