Python
Lambda Functions
Multiline Lambda
Programming Limitations
Python Features

No Multiline Lambda in Python Why not?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Python intentionally restricts lambdas to a single expression. Guido van Rossum rejected multiline lambdas because they conflict with Python's indentation-based syntax. Embedding an indented block inside an expression creates ambiguity for both the parser and human readers. The design philosophy is that if you need multiple statements, use a def statement. Lambda is for short, inline expressions only.

What Lambda Can Do

python
1# Single expression, return is implicit
2square = lambda x: x ** 2
3print(square(5))  # 25
4
5# Multiple arguments
6add = lambda a, b: a + b
7print(add(3, 7))  # 10
8
9# Conditional expression (ternary)
10classify = lambda x: "positive" if x > 0 else "negative" if x < 0 else "zero"
11print(classify(-5))  # negative
12
13# Calling functions
14process = lambda s: s.strip().lower().replace(" ", "_")
15print(process("  Hello World  "))  # hello_world

Lambda can do anything that fits in a single expression. The limitation is that it cannot contain statements (assignments, loops, try/except, print as a statement in Python 2).

What Lambda Cannot Do

python
1# CANNOT: multiple statements
2lambda x: (
3    y = x + 1     # SyntaxError: assignment is a statement
4    return y * 2   # SyntaxError: return is a statement
5)
6
7# CANNOT: loops
8lambda items: (
9    for item in items:  # SyntaxError
10        process(item)
11)
12
13# CANNOT: try/except
14lambda x: (
15    try:               # SyntaxError
16        return int(x)
17    except ValueError:
18        return 0
19)

Why Not Allow Multiline Lambda?

1. Indentation Ambiguity

Python uses indentation for blocks. Embedding an indented block inside an expression creates parsing ambiguity:

python
1# How would this be parsed?
2result = sorted(items, key=lambda x:
3    y = x.name
4    z = y.lower()
5    return z
6)
7
8# Where does the lambda body end and the sorted() call continue?
9# The parser cannot tell from indentation alone.

2. Guido's Explicit Rejection

Guido van Rossum has stated multiple times that multiline lambda would damage Python's readability. From his blog:

"Any solution to make lambda multiline would be at best a kludge... I find any solution unacceptable that embeds an indentation-based block in the middle of an expression."

3. def Already Solves This

python
1# Instead of a hypothetical multiline lambda:
2# process = lambda x: (statement1; statement2; return result)
3
4# Just use def:
5def process(x):
6    y = x.strip()
7    z = y.lower()
8    return z.replace(" ", "_")
9
10result = sorted(items, key=process)

A named function with def is always clearer than a multiline anonymous function.

Workarounds

Chained Expressions

python
1# Multiple operations in one expression using method chaining
2process = lambda s: s.strip().lower().replace(" ", "_")
3
4# Tuple unpacking trick (evaluates all, returns last)
5compute = lambda x: (x + 1, x * 2, (x + 1) * (x * 2))[-1]

Walrus Operator (Python 3.8+)

python
# Assignment expressions allow some multi-step logic
compute = lambda x: (y := x * 2, z := y + 1, z ** 2)[-1]
print(compute(3))  # (3*2=6, 6+1=7, 7**2=49) → 49

This works but is hard to read. A def is almost always better.

Helper Functions

python
1# Break complex logic into small named functions
2def normalize(s):
3    return s.strip().lower()
4
5def validate(s):
6    return s if len(s) > 0 else "unknown"
7
8# Compose them
9pipeline = lambda s: validate(normalize(s))
10
11# Or use functools.reduce for composition
12from functools import reduce
13def compose(*funcs):
14    return reduce(lambda f, g: lambda x: f(g(x)), funcs)
15
16process = compose(validate, normalize)
17print(process("  Hello  "))  # hello

Conditional Logic

python
1# Ternary works in lambda
2safe_div = lambda a, b: a / b if b != 0 else 0
3
4# Nested ternary (hard to read)
5grade = lambda score: (
6    "A" if score >= 90 else
7    "B" if score >= 80 else
8    "C" if score >= 70 else
9    "F"
10)
11print(grade(85))  # B

Dictionary Dispatch

python
1# Replace multi-branch lambda with dict lookup
2ops = {
3    "+": lambda a, b: a + b,
4    "-": lambda a, b: a - b,
5    "*": lambda a, b: a * b,
6    "/": lambda a, b: a / b if b != 0 else 0,
7}
8
9calc = lambda op, a, b: ops[op](a, b)
10print(calc("+", 3, 7))  # 10

When to Use Lambda

python
1# GOOD: short, clear, used once
2sorted(names, key=lambda x: x.lower())
3filtered = filter(lambda x: x > 0, numbers)
4mapped = map(lambda x: x ** 2, numbers)
5
6# GOOD: simple callback
7button.on_click(lambda event: print("clicked"))
8
9# BAD: complex logic that needs a name
10process = lambda data: (
11    [item.strip().lower() for item in data if item]
12    if isinstance(data, list) else
13    data.strip().lower() if isinstance(data, str) else
14    str(data)
15)
16# Use def instead!

Lambda vs def Comparison

python
1# Lambda
2square = lambda x: x ** 2
3
4# def: equivalent but with a name in tracebacks
5def square(x):
6    return x ** 2
7
8# Lambda shows as <lambda> in errors:
9# TypeError: <lambda>() takes 1 positional argument but 2 were given
10
11# def shows the function name:
12# TypeError: square() takes 1 positional argument but 2 were given

Named functions produce better error messages and are easier to debug.

Common Pitfalls

  • Assigning lambda to a variable: square = lambda x: x ** 2 is functionally identical to def square(x): return x ** 2 but with worse tracebacks. PEP 8 says: "Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier."
  • Late binding in loops: [lambda: i for i in range(5)] creates 5 lambdas that all return 4 (the final value of i). Fix: [lambda i=i: i for i in range(5)] captures the current value.
  • Readability over cleverness: Walrus operator tricks and tuple indexing make lambda do more but hurt readability. If you need a workaround, use def.
  • Type annotations: Lambda does not support type hints. Use def when type annotations matter for documentation or static analysis.
  • Closures and mutable state: Lambda captures variables by reference, not by value. If the variable changes after the lambda is created, the lambda sees the new value.

Summary

  • Python lambdas are restricted to a single expression by design
  • Multiline lambda conflicts with Python's indentation-based block syntax
  • Use def for any function that needs multiple statements. It is clearer and produces better error messages
  • The walrus operator and chained expressions extend what a single expression can do, but def is almost always more readable
  • Lambda is best for short, throwaway functions passed as arguments to sorted(), map(), filter(), and callbacks
  • PEP 8 discourages assigning lambdas to variables. Use def instead

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.