I mostly use lambda functions but sometimes use nested functions that seem to provide the same behavior.
Here are some trivial examples where they functionally do the same thing if either were found within another function:
Lambda function
>>> a = lambda x : 1 + x
>>> a(5)
6
Nested function
>>> def b(x): return 1 + x
>>> b(5)
6
Are there advantages to using one over the other? (Performance? Readability? Limitations? Consistency? etc.)
Does it even matter? If it doesn't then does that violate the Pythonic principle:
“There should be one—and preferably only one—obvious way to do it”.
Practically speaking, to me there are two differences:
The first is about what they do and what they return:
def is a keyword that doesn't return anything and creates a 'name' in the local namespace.
lambda is a keyword that returns a function object and does not create a 'name' in the local namespace.
Hence, if you need to call a function that takes a function object, the only way to do that in one line of python code is with a lambda. There's no equivalent with def.
In some frameworks this is actually quite common; for example, I use Twisted a lot, and so doing something like
is quite common, and more concise with lambdas.
The second difference is about what the actual function is allowed to do.
For example,
works as expected, while
is a SyntaxError.
Of course, there are workarounds - substitute
print
withsys.stdout.write
, orimport
with__import__
. But usually you're better off going with a function in that case.A major difference is that you can not use
def
functions inline, which is in my opinion the most convenient use case for alambda
function. For example when sorting a list of objects:I would therefore suggest keeping the use of lambdas to this kind of trivial operations, which also do not really benefit from the automatic documentation provided by naming the function.
If you need to assign the
lambda
to a name, use adef
instead.def
s are just syntactic sugar for an assignment, so the result is the same, and they are a lot more flexible and readable.lambda
s can be used for use once, throw away functions which won't have a name.However, this use case is very rare. You rarely need to pass around unnamed function objects.
The builtins
map()
andfilter()
need function objects, but list comprehensions and generator expressions are generally more readable than those functions and can cover all use cases, without the need of lambdas.For the cases you really need a small function object, you should use the
operator
module functions, likeoperator.add
instead oflambda x, y: x + y
If you still need some
lambda
not covered, you might consider writing adef
, just to be more readable. If the function is more complex than the ones atoperator
module, adef
is probably better.So, real world good
lambda
use cases are very rare.While agreeing with the other answers, sometimes it's more readable. Here's an example where
lambda
comes in handy, in a use case I keep encountering of an N dimensionaldefaultdict
.Here's an example:
I find it more readable than creating a
def
for the second dimension. This is even more significant for higher dimensions.One use for lambdas I have found... is in debug messages.
Since lambdas can be lazily evaluated you can have code like this:
instead of possibly expensive:
which processes the format string even if the debug call does not produce output because of current logging level.
Of course for it to work as described the logging module in use must support lambdas as "lazy parameters" (as my logging module does).
The same idea may be applied to any other case of lazy evaluation for on demand content value creation.
For example this custom ternary operator:
instead of:
with lambdas only the expression selected by the condition will be evaluated, without lambdas both will be evaluated.
Of course you could simply use functions instead of lambdas, but for short expressions lambdas are (c)leaner.
Performance:
Creating a function with
lambda
is slightly faster than creating it withdef
. The difference is due todef
creating a name entry in the locals table. The resulting function has the same execution speed.Readability:
Lambda functions are somewhat less readable for most Python users, but also much more concise in some circumstances. Consider converting from using non-functional to functional routine:
As you can see, the
lambda
version is shorter and "easier" in the sense that you only need to addlambda v:
to the original non-functional version to convert to the functional version. It's also a lot more concise. But remember, a lot of Python users will be confused by the lambda syntax, so what you lose in length and real complexity might be gained back in confusion from fellow coders.Limitations:
lambda
functions can only be used once, unless assigned to a variable name.lambda
functions assigned to variable names have no advantage overdef
functions.lambda
functions can be difficult or impossible to pickle.def
functions' names must be carefully chosen to be reasonably descriptive and unique or at least otherwise unused in scope.Consistency:
Python mostly avoids functional programming conventions in favor of procedural and simpler objective semantics. The
lambda
operator stands in direct contrast to this bias. Moreover, as an alternative to the already prevalentdef
, thelambda
function adds diversity to your syntax. Some would consider that less consistent.Pre-existing functions:
As noted by others, many uses of
lambda
in the field can be replaced by members of theoperator
or other modules. For instance:Using the pre-existing function can make code more readable in many cases.
The Pythonic principle: “There should be one—and preferably only one—obvious way to do it”
That's similar to the single source of truth doctrine. Unfortunately, the single-obvious-way-to-do-it principle has always been more an wistful aspiration for Python, rather than a true guiding principal. Consider the very-powerful array comprehensions in Python. They are functionally equivalent to the
map
andfilter
functions:lambda
anddef
are the same.It's a matter of opinion, but I would say that anything in the Python language intended for general use which doesn't obviously break anything is "Pythonic" enough.