Skip to main content
Intermediate Python2026-08-03 Β· 9 min read

Python Lambda Functions Explained: The 5 Legitimate Uses (and When to Use def Instead)

Most Python tutorials teach lambda syntax and then stop. That's how you end up with codebases full of lambda x: x style one-liners doing the work of a proper def. This post covers the opposite: exactly where lambdas belong, exactly where they don't, and why PEP 8 explicitly tells you to name your function most of the time.

By the end you'll know the 5 concrete places lambda actually beats def, and you'll stop reaching for it out of habit everywhere else.

The syntax

A lambda is a single-expression, anonymous function. That's the whole language feature.

β–Ά PYTHONeditable Β· runs in your browser

Two hard constraints. First: exactly one expression. You cannot put a statement inside a lambda, so no if:, no for:, no return, no assignments (except for the walrus operator :=, which is technically an expression). Second: no name. The function has __name__ == "<lambda>", which shows up in stack traces as an unhelpful blank.

Both constraints exist for a reason. The whole point of lambda is inline throwaway logic that doesn't need a name because you're passing it directly somewhere.

Lambda vs def: performance

They compile to nearly identical bytecode. Any performance argument for one over the other is folklore. Pick by readability, not speed.

β–Ά PYTHONeditable Β· runs in your browser

The def version emits the same 4 opcodes plus a STORE_NAME for the function name. Millionths of a second.

The 5 legitimate uses

1. Sort key

The single most common good use. sorted and list.sort take a key= callable that gets called once per element to produce the comparison value.

β–Ά PYTHONeditable Β· runs in your browser

Naming this function def get_age(u): return u["age"] on the line above adds noise without adding meaning. The lambda IS the meaning.

Same story with min, max, heapq.nsmallest, itertools.groupby, and Pandas' sort_values(key=...).

2. filter / map inside a comprehension or one-liner

When you genuinely need a one-shot transform:

β–Ά PYTHONeditable Β· runs in your browser

Honestly, most of the time a list comprehension is cleaner ([x * x for x in range(10)]). But when you're chaining into an existing pipeline that expects a callable, lambda fits.

3. GUI / event callbacks

Tkinter, curses, and any event-loop UI framework expects callables for click handlers. When the handler is a one-liner that needs to close over a variable:

β–Ά PYTHONeditable Β· runs in your browser

The l=label default-argument trick captures the current value, avoiding the classic late-binding closure bug. Without lambda, you'd need a factory function for every loop iteration.

4. Decorator arguments

When a decorator itself takes a callable and you want to configure it inline:

β–Ά PYTHONeditable Β· runs in your browser

The on=lambda err: ... predicate is short-lived and specific to this call site. A named function would live in module scope and clutter the file.

5. Pandas .apply and column ops

Data-analysis code is lambdas' native habitat:

β–Ά PYTHONeditable Β· runs in your browser

Naming these adds nothing. The lambda body IS the column-transform semantic.

The 3 anti-patterns to kill

1. Assigning a lambda to a variable

If you're doing this:

β–Ά PYTHONeditable Β· runs in your browser

Use def instead:

β–Ά PYTHONeditable Β· runs in your browser

They're the same amount of code, but the def version gives you a real __name__, works with debuggers, and doesn't confuse readers looking for the function definition. PEP 8 says exactly this. Ruff has a rule for it (E731).

2. Multi-line lambdas via nested expressions

Python does not have multi-statement lambdas. When you feel the urge to write:

β–Ά PYTHONeditable Β· runs in your browser

Just write a def. The tuple-of-expressions trick works but is unreadable.

3. Lambda when a stdlib callable exists

You almost never need to write lambda x: x.lower() when str.lower (bound-method-style) works:

β–Ά PYTHONeditable Β· runs in your browser

Same for abs, len, str, int, operator.itemgetter, operator.attrgetter. Reach for these first, lambda second.

When def always wins

The moment your function needs a docstring, does anything that isn't a single expression, or gets called from more than one place β€” use def. The named function shows up in profilers, in stack traces, in help(), and in code review as a distinct thing to review.

FAQ

Is a lambda faster than a def function?

No. They compile to nearly identical bytecode. Choose by readability, not speed.

Can a lambda have multiple statements?

No. A lambda is a single expression. If you need statements (if, for, return, assignments), use def. The walrus operator := is technically an expression and works inside a lambda.

Why does PEP 8 tell me not to assign lambdas to variables?

Because it hides the function from every tool that reads __name__: debuggers, tracebacks, profilers, help(). The equivalent def is the same amount of code and reads much better.

When should I prefer str.lower over lambda w: w.lower()?

Almost always. Unbound methods and stdlib callables (abs, len, str.lower, operator.itemgetter) are shorter and clearer than the equivalent lambda. Use lambda only when no such callable exists.

Do lambdas work in async code?

Yes, but you can't await inside a lambda (await is a statement). For most async callbacks, define an async def. If the callback is fully synchronous and you're passing it to something like asyncio.get_event_loop().call_later, a plain lambda is fine.

Comprehensions are the most idiomatic Python transformation tool β€” our list comprehension builder shows how to convert a for-loop into one live. Or start Foundations to build the muscle memory across every language feature.

Ready to try it?

15 lessons free after a free signup β€” no card. Sample the platform, then decide.

Start free β†’

Or unlock every lesson

Pro β€” $12/mo, unlimited AI, cancel any time. Refund within 14 days worldwide.

See Pro plans β†’

Get one Python lesson + one career idea every Friday

No spam, no "buy our course now". Three bullets, every Friday. Unsubscribe with one click.