skip to content

What is a Python lambda expression, and how does it differ from a def function?

level: juniorimportance: must knowfreq 78%

answer

  1. An expression, not a statement
  2. One expression, no block
  3. The value is returned implicitly
  4. Same function object def would build
  5. Its __name__ is '<lambda>'

basics

~20 s

A lambda expression builds an anonymous function whose body is a single expression, returned implicitly. def is a statement that names the function and can contain any block of code. Both create the same kind of function object.

solid answer

~50 s

`lambda params: expression` is an *expression* that evaluates to a function object — the same kind of object `def` produces, just built without a name. The body is exactly one expression whose value is returned implicitly; there is no `return` keyword and no room for statements. Because it is an expression, it can sit wherever a value is expected: an argument such as `sorted(rows, key=...)`, a dict value, a callback slot. `def` is a statement: it binds a name in the enclosing namespace, its body may be any block, and it can carry a docstring and parameter annotations. Everything else is shared — closures, default values, `*args`/`**kwargs`, the calling convention, the cost of a call. So a lambda is not a faster or lighter function; it is the same function with a syntax that fits inline and a body restricted to one expression.

code

python · 9 lines
python
square = lambda n: n * n

def cube(n):
    """Return n cubed."""
    return n ** 3

print(square(5), cube(5))
print(square.__name__, square.__doc__)
print(cube.__name__, cube.__doc__)

go deeper

for a junior

Be ready to write lambda x: x * 2 on the spot, say that it evaluates to a function object, and explain that the single expression is returned without a return keyword. Knowing when to reach for def instead is the other half of the answer.

for a middle

Explain the mechanics: lambda is an expression and def is a statement, both build a types.FunctionType, and the differences are metadata — __name__ of '<lambda>', no docstring, no parameter annotations. Be able to say why one can appear inline and the other cannot.

for a senior

An interviewer expects you to police the boundary in review: inline throwaway callables are fine, a lambda bound to a name is a def waiting to happen, and anything needing a loop, a try or an early return was never a lambda. Say what it costs in tracebacks and logs when the rule is ignored.

for a principal

Own the codebase-wide position: state where lambdas are welcome, where they are banned, and why the rule is about readability and debuggability rather than performance, so reviewers stop arguing the point per pull request.

## The syntax The form is `lambda parameter_list: expression`. There are no parentheses around the parameter list and no parentheses around the body; the single colon separates the two. `lambda: 0` takes no parameters at all. The whole construct is an **expression**, so it evaluates to a value — a function object — the moment it is reached, exactly the way `3 + 4` evaluates to `7`. That is the one structural difference worth memorising. `def` is a *statement*. A statement can only appear where the grammar allows statements: at module level, in a class body, inside another function. An expression can appear anywhere a value is expected. That is why a lambda can be written directly inside a call's argument list, inside a dict literal, as a default parameter value, or as one branch of a conditional expression, while a `def` in any of those places is a syntax error. ## The object it produces Evaluating a lambda produces an ordinary function object — the same `types.FunctionType` that a `def` produces. It is called the same way, it participates in closures the same way, it supports defaults and `*args`/`**kwargs` the same way, and it costs the same to call. Nothing about a lambda is optimised, inlined or made cheaper by the compiler; the bytecode for the body is the bytecode you would get from the equivalent `def`. The visible differences are metadata. A lambda's `__name__` and the tail of its `__qualname__` are the literal string `'<lambda>'`, because there was no name to record. Its `__doc__` is `None`, since a docstring is a statement-position string literal and a lambda has no statement positions. Its parameters carry no annotations, because the parameter list of a lambda cannot be annotated at all. A `def` records a real name, can carry a docstring as its first statement, and can annotate every parameter and its return. ```python import types square = lambda n: n * n def cube(n): return n ** 3 print(type(square) is types.FunctionType) # True print(square.__name__, cube.__name__) # <lambda> cube ``` ## The implicit return A lambda has no `return` keyword; the value of its single expression *is* the return value. Writing `lambda x: return x` is a syntax error, and so is any other statement. Candidates who have only seen the form in a `key=` argument often assume a lambda "does something" rather than "evaluates to something" — the correction is that a lambda body is a value-producing expression and nothing else. If the body has no useful value, for instance `lambda: print("tick")`, the lambda still returns something: whatever the expression evaluated to, here `None`. ## Where it earns its place The honest use is a short, throwaway callable passed straight into another call and never referred to again: an ordering key, a small callback, a factory argument, a default for a dependency-injection slot. In those positions the lambda is read in the same glance as the call it sits in, and giving it a name would add a line without adding information. The honest limits follow from the grammar. Anything that needs a loop body, a `try`, a `with`, an assignment statement, an early return, a raise, several steps, or a docstring needs a `def`. And PEP 8 explicitly says that if you are about to bind a lambda to a name with `=`, write `def` instead — the name is the only thing a `def` was giving you, and the `def` also gives back the traceback name, the docstring and the annotations. ## Two myths to kill The first is that lambdas are faster. They are not; both forms compile to the same code object machinery, and the call overhead is identical. The second is that a lambda is a different, lesser sort of callable — some "expression" that is not a real function. It is a real function: it has a `__code__`, it closes over enclosing variables, it can be stored, passed, returned and introspected. The only thing it lacks is a name of its own and the ability to hold statements. ## What an interviewer is checking The question is a screening question, and the pass mark is low: know the syntax, know the body is one expression with an implicit return, know that the result is an ordinary function object, and know that `def` is the answer whenever the body would need more than one expression or the function needs a name. Candidates who add "and PEP 8 says not to assign one to a variable" are showing they have read the style guide rather than only copied examples.

  • Does a lambda create a different type of object than a function defined with def?
    No. Both create a `types.FunctionType` object with a `__code__`, defaults, and closure support, and both are called identically. The differences are metadata: a lambda's `__name__` and the tail of its `__qualname__` are the string `'<lambda>'`, its `__doc__` is `None`, and its parameters carry no annotations.
  • Where can a lambda appear that a def cannot?
    Anywhere an expression is allowed and a statement is not: inside a call's argument list, as a value in a dict or list literal, as a default parameter value, inside a conditional expression, inside a comprehension. A `def` in any of those positions is a syntax error, because `def` is a statement.
  • Is a lambda faster to call than an equivalent def function?
    No. The body compiles to the same bytecode and the call goes through the same path, so the cost is the same. The only saving is source lines. If someone reaches for a lambda for speed, they are optimising the wrong thing; the real reasons are inline placement and not needing a name.

A def is a labelled tool hung on the workshop wall; a lambda is the same tool handed to you unlabelled, mid-job, because you will use it once and let go of it.

saying these in an interview costs you the question

  • Claims a lambda is faster or cheaper than a def
  • Thinks a lambda body needs an explicit return
  • Believes a lambda cannot take default or keyword arguments
  • Calls a lambda a different type from a normal function
  • Thinks several statements fit in a body if separated by semicolons
  • Says a lambda cannot close over enclosing variables

context