More preferably: lambda functions or nested functions ( def )?
There is one advantage to using lambdas over a regular function (they are created in an expression) and several disadvantages. For this reason, I prefer to create functions with the def keyword rather than lambdas.
The first point is the same type of object
Lambda leads to the same type of object as a regular function
>>> l = lambda: 0 >>> type(l) <class 'function'> >>> def foo(): return 0 ... >>> type(foo) <class 'function'> >>> type(foo) is type(l) True
Because lambda expressions are functions, they are first-class objects.
Both lambdas and functions:
- can be passed as an argument (same as a regular function)
- when created inside an external function, it becomes a closure over the local elements of this external function
But the default lambdas lack some of the things that functions get through the full function definition syntax.
Lamb __name__ is '<lambda>'
After all, lambdas are anonymous functions, so they donโt know their name.
>>> l.__name__ '<lambda>' >>> foo.__name__ 'foo'
Thus, lambda cannot be found programmatically in their namespace.
This limits certain things. For example, foo can be searched using serialized code, while l cannot:
>>> import pickle >>> pickle.loads(pickle.dumps(l)) Traceback (most recent call last): File "<stdin>", line 1, in <module> _pickle.PicklingError: Can't pickle <function <lambda> at 0x7fbbc0464e18>: attribute lookup <lambda> on __main__ failed
We can just find foo - because he knows his name:
>>> pickle.loads(pickle.dumps(foo)) <function foo at 0x7fbbbee79268>
There are no annotations or documentation lines in lambdas
Basically, lambdas are not documented. Let rewrite foo be better documented:
def foo() -> int: """a nullary function, returns 0 every time""" return 0
Now foo has the documentation:
>>> foo.__annotations__ {'return': <class 'int'>} >>> help(foo) Help on function foo in module __main__: foo() -> int a nullary function, returns 0 every time
Whereas we do not have the same mechanism for providing the same information to lambdas:
>>> help(l) Help on function <lambda> in module __main__: <lambda> lambda (...)
But we can hack them into:
>>> l.__doc__ = 'nullary -> 0' >>> l.__annotations__ = {'return': int} >>> help(l) Help on function <lambda> in module __main__: <lambda> lambda ) -> in nullary -> 0
But perhaps help is displayed due to an error.
Lambdas can only return an expression
Lambda cannot return complex expressions, only expressions.
>>> lambda: if True: 0 File "<stdin>", line 1 lambda: if True: 0 ^ SyntaxError: invalid syntax
Expressions can be quite complex, and if you try your best, you can probably do the same with lambdas, but the extra complexity is more damaging to writing clear code.
We use Python for clarity and ease of maintenance. Overuse of lambdas may work against this.
The only plus for lambda: can be created in one expression
This is the only potential. Since you can create a lambda expression with an expression, you can create it inside a function call.
Creating a function inside a function call avoids a (inexpensive) name lookup compared to a function created elsewhere.
However, since Python is strictly evaluated, it offers no other performance gain other than avoiding name lookups.
For a very simple expression, I could choose a lambda.
I also tend to use lambdas when working with interactive Python to avoid multiple lines when one will do. I use the following kind of code format when I want to pass an argument to the constructor when calling timeit.repeat :
import timeit def return_nullary_lambda(return_value=0): return lambda: return_value def return_nullary_function(return_value=0): def nullary_fn(): return return_value return nullary_fn
And now:
>>> min(timeit.repeat(lambda: return_nullary_lambda(1))) 0.24312214995734394 >>> min(timeit.repeat(lambda: return_nullary_function(1))) 0.24894469301216304
I believe that the small time difference above can be related to finding a name in return_nullary_function - note that it is very insignificant.
Conclusion
Lambdas are good for informal situations when you want to minimize lines of code in favor of highlighting a special situation.
Lambdas are bad for more formal situations when you need clarity for code editors that come later, especially when they are nontrivial.
We know that we must give our objects good names. How can we do this if the object does not have a name?
For all these reasons, I prefer to create functions with def instead of lambda .