A lambda function in Python is a small, anonymous function defined with the lambda keyword instead of def. It can accept any number of arguments but its body is restricted to a single expression. The value of that expression is automatically returned. Lambdas are not a replacement for regular functions; they are a specialized tool for situations where a short, throwaway function is needed inline, particularly as an argument to another function. Understanding when to use lambda and when to reach for def is a skill that develops with experience, and this article gives you the rules and examples to build that judgment.
The article on define and call Python functions covered the standard way to create named functions with def. Lambdas complement that mechanism by providing a way to create function objects without giving them names, directly in the middle of an expression. This is why lambdas are called anonymous functions. They exist as objects that can be passed around, stored, and called, but they never appear in the module's namespace with a permanent name unless you explicitly assign one to a variable, which defeats much of the purpose.
Lambda syntax and basic examples
The syntax of a lambda is minimal: the keyword lambda, followed by zero or more argument names separated by commas, a colon, and a single expression. The expression is evaluated and returned when the lambda is called. There is no return keyword because returning is the only thing a lambda can do:
double = lambda x: x * 2
print(double(5)) # 10This lambda takes one argument x and returns x multiplied by 2. It is functionally identical to defining a function with def double(x): return x * 2, but it is written inline as an expression. Assigning a lambda to a variable is valid Python but is discouraged by PEP 8, the Python style guide. The whole point of lambdas is to be anonymous. If you are assigning one to a name, you should use def instead, because def gives you better tracebacks, docstrings, and readability.
The real use of lambdas is passing them directly as arguments without ever giving them a name. The sorted function's key parameter is the classic example. Instead of defining a named function that extracts a sort key and passing it to sorted, you write the extraction inline as a lambda:
students = [("Ada", 92), ("Rex", 78), ("Maya", 85)]
ranked = sorted(students, key=lambda student: student[1], reverse=True)The lambda extracts the score, the second element of each tuple, and sorted uses it to determine the order. The lambda is short, its purpose is obvious from context, and it has no reason to exist outside this single sorted call. This is the ideal use case for lambda: a simple, single-use function that would be more ceremony than it is worth to define with def.
Lambdas with multiple arguments
A lambda can accept any number of arguments, including positional, keyword, and even *args and **kwargs patterns. The argument list follows the same rules as a def function, minus type annotations and default values, which are syntactically valid in lambdas but rarely used in practice:
A lambda that adds two numbers looks like lambda a, b: a + b, and a lambda with a default argument looks like lambda name, greeting="Hello": f"{greeting}, {name}!". Both work correctly, but both are also better written as def functions because they are assigned to names. The point of showing them is that lambda's argument handling is not limited to a single argument; it supports the full range of argument patterns, constrained only by the single-expression body.
Lambdas in map, filter, and other higher-order functions
Python's built-in map and filter functions accept a function as their first argument and an iterable as their second. Lambdas are a natural fit for this pattern because the function argument is typically a short transformation or predicate that has no reason to exist as a named entity:
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x ** 2, numbers))
evens = list(filter(lambda x: x % 2 == 0, numbers))The first lambda, passed to map, squares each number. The second lambda, passed to filter, tests whether a number is even. Both are single-use transformations that would be less readable if extracted into separate named functions that the reader had to find and understand. The lambda keeps the transformation visible at the point of use, which is exactly where the reader needs it.
It is worth noting that many Python developers prefer list comprehensions and generator expressions over map and filter with lambdas. The expression [x ** 2 for x in numbers] is often considered more readable than list(map(lambda x: x ** 2, numbers)). This is a style preference, not a rule, but it is a widespread preference in the Python community. Lambdas with sorted, max, min, and similar functions where no comprehension-based alternative exists are the least controversial use of lambdas.
The limitations of lambda
The single-expression restriction is the defining constraint of lambdas. You cannot use statements like assignment, loops, if-elif-else blocks, try-except, with, or import inside a lambda body. You cannot have multiple expressions separated by semicolons. You cannot include a docstring or annotations. These restrictions are intentional: if your logic needs any of these features, it is complex enough to deserve a name and a proper def.
A lambda with a conditional expression, using the inline if-else syntax, is allowed because the ternary operator is an expression, not a statement:
safe_divide = lambda a, b: a / b if b != 0 else NoneThis lambda uses the conditional expression to handle division by zero. It fits on one line and is still readable. But if the logic needed multiple conditions, nested ternaries, or any kind of loop, the lambda form would become unreadable, and a def function would be the correct choice. The guideline is simple: if a lambda is longer than about sixty characters or requires mental effort to parse, replace it with def. The maintainability gain from a clear function name and a properly indented body outweighs the minor convenience of keeping the function inline.
Lambda and variable capture
A subtle but important behavior: lambdas capture variables from their enclosing scope, not their values at the time the lambda is defined. This is the same closure behavior that regular nested functions exhibit, and it can lead to surprising results when lambdas are created in loops:
funcs = []
for i in range(3):
funcs.append(lambda: i)
print([f() for f in funcs]) # [2, 2, 2], not [0, 1, 2]All three lambdas capture the variable i, not its value at each iteration. When the lambdas are called after the loop, i has the value 2 from the final iteration. This is a common pitfall, and the fix is to bind the current value as a default argument: lambda i=i: i. Default argument values are evaluated at definition time, so each lambda captures the value of i from its own iteration. The article on closures in Python explores this capture behavior in greater depth.
The variable capture behavior of lambdas is identical to that of nested def functions, and it is not a lambda-specific quirk. Understanding closures, not memorizing lambda-specific rules, is what prevents bugs with captured variables. The same fix, binding the value as a default argument, works for both lambdas and nested defs.
Rune AI
Key Insights
- A lambda function is defined with the lambda keyword and consists of a single expression that is implicitly returned.
- Lambda syntax: lambda arguments: expression. For example: lambda x: x * 2.
- Lambdas are most useful as inline arguments to functions like sorted, map, and filter.
- A lambda cannot contain statements, assignments, loops, or multiple expressions.
- If a lambda is longer than a single readable line or needs a name for reuse, use def instead.
Frequently Asked Questions
What is a lambda function in Python?
When should I use lambda instead of def?
Can a Python lambda contain multiple statements or a return statement?
Conclusion
Lambda functions are a concise tool for writing short, anonymous functions inline, particularly as arguments to higher-order functions like sorted, map, and filter. They fill a specific niche in Python and are not a replacement for def. When a function needs a name, multiple statements, or will be reused, use def. When you need a quick one-liner that reads clearly as an expression, lambda is the right choice.
More in this topic
Define and Call Python Functions
Learn the exact syntax for defining and calling Python functions with the def keyword, including naming rules, the function body, and how the call stack works.
Python Function Parameters and Arguments
Learn the difference between parameters and arguments, how to pass values by position and by keyword, and the rules for default parameter values.
Python Functions Explained
Learn what Python functions are, why they matter for organizing code, and how they form the foundation of non-trivial programs.