views:

3316

answers:

9

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

Is there advantages to using one over the other? (Performance? Readability? Limitations? Consistency? etc.) Does it even matter? If doesn't then does that violate the Pythonic principle: “There should be one—and preferably only one—obvious way to do it”.

+18  A: 

If you need to assign the lambda to a name, use a def instead. defs are just syntactic sugar for an assignment, so the result is the same, and they are a lot more flexible and readable.

lambdas 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() and filter() 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, like operator.add instead of lambda x, y: x + y

If you still need some lambda not covered, you might consider writing a def, just to be more readable. If the function is more complex than the ones at operator module, a def is probably better.

So, real world good lambda use cases are very rare.

nosklo
lambda's *may* be good for *use once, throw away* functions, but frequently they aren't even good for that. There is *nothing* you can do with a lambda-created function that you can't do with a def-created function; the difference is mostly in readability. Sometimes terse is good, often it isn't.
Thomas Wouters
Care to add that where lambdas used to be useful, nowadays you can often use functools.partial?
Torsten Marek
@Torsten: I think functools.partial is overrated. I'd rather def a function to call the other one with the extra params most cases.
nosklo
@THomas Wouters: I agree, and I have changed the answer to reflect that. Thanks.
nosklo
+4  A: 

I agree with nosklo's advice: if you need to give the function a name, use def. I reserve lambda functions for cases where I'm just passing a brief snippet of code to another function, e.g.:

a = [ (1,2), (3,4), (5,6) ]
b = map( lambda x: x[0]+x[1], a )
Dan
In most combinations of map/lambda, you can replace it with a list comprehension or more appropriate function. For example, "map (sum, a)" or "[x[0] + x[1] for x in a]"
John Millikin
Yes, that's true. Sometimes I prefer map() though. This was mostly just a contrived example of using an in-line function.
Dan
+6  A: 

In this interview, Guido van Rossum says he wishes he hadn't let 'lambda' into Python:

"Q. What feature of Python are you least pleased with?

Sometimes I've been too quick in accepting contributions, and later realized that it was a mistake. One example would be some of the functional programming features, such as lambda functions. lambda is a keyword that lets you create a small anonymous function; built-in functions such as map, filter, and reduce run a function over a sequence type, such as a list.

In practice, it didn't turn out that well. Python only has two scopes: local and global. This makes writing lambda functions painful, because you often want to access variables in the scope where the lambda was defined, but you can't because of the two scopes. There's a way around this, but it's something of a kludge. Often it seems much easier in Python to just use a for loop instead of messing around with lambda functions. map and friends work well only when there's already a built-in function that does what you want.

IMHO, Iambdas can be convenient sometimes, but usually are convenient at the expense of readibility. Can you tell me what this does:

str(reduce(lambda x,y:x+y,map(lambda x:x**x,range(1,1001))))[-10:]

I wrote it, and it took me a minute to figure it out. This is from Project Euler - i won't say which problem because i hate spoilers, but it runs in 0.124 seconds :)

Chris Lawlor
Do note that the interview is rather old, and Python has long since added nested scopes, which makes the argument he gives against lambda no longer relevant. I'm sure he still regrets lambda, but not enough to remove it in Python 3.0.
Thomas Wouters
Last ten digits of the sum of the square numbers less than 1 million. And really your example should be an argument against one-liners, not lambdas. Also, you should have used the built-in sum function instead of reducing with a lambda: str(sum(map(lambda x:x**x, range(1001))))[:-10]
Triptych
@Triptych: `x**x` and `x*x` (square) are not the same.
J.F. Sebastian
+2  A: 

The primary use of lambda has always been for simple callback functions, and for map, reduce, filter, which require a function as an argument. With list comprehensions becoming the norm, and the added allowed if as in:

x = [f for f in range(1, 40) if f % 2]

it's hard to imagine a real case for the use of lambda in daily use. As a result, I'd say, avoid lambda and create nested functions.

Andrew Gwozdziewycz
A: 

I agree with nosklo. By the way, even with a use once, throw away function, most of the time you just want to use something from the operator module.

E.G :

You have a function with this signature : myFunction(data, callback function).

You want to pass a function that add 2 elements.

Using lambda :

myFunction(data, (lambda x, y : x + y))

The pythonic way :

import operator
myFunction(data, operator.add)

Or course this is a simple example, but there is a lot of stuff the operator module provides, including the items setters / getters for list and dict. Really cool.

e-satis
+5  A: 

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

d.addCallback(lambda result: setattr(self, _someVariable, result))

is quite common, and more concise with lambdas.

The second difference is about what the actual function is allowed to do.

  • A function defined with 'def' can contain any python code
  • A function defined with 'lambda' has to evaluate to an expression, and can thus not contain statements like print, import, raise, ...

For example,

def p(x): print x

works as expected, while

lambda x: print x

is a SyntaxError.

Of course, there are workarounds - substitute print with sys.stdout.write, or import with __import__. But usually you're better off going with a function in that case.

Thomas Vander Stichele
You can't actually make assignments inside a lambda.However, the way around it is to use "setattr". Ex:d.addCallback(lambda result: setattr(self,"_someVar",result))Be sure to initialize self._someVar before.
elmarco
A: 

If you are just going to assign the lambda to a variable in the local scope, you may as well use def because it is more readable and can be expanded more easily in the future:

fun = lambda a, b: a ** b # a pointless use of lambda
map(fun, someList)

or

def fun(a, b): return a ** b # more readable
map(fun, someList)
too much php
A: 

lambda is usefull for generating new functions:

def somefunc(x): return lambda y: x+y
f = somefunc(10)
f(2)
>>> 12
f(4)
>>> 14
+1  A: 

An important limitation of lambdas is that they cannot contain anything besides an expression. It's nearly impossible for a lambda expression to produce anything besides trivial side effects, since it cannot have anywhere near as rich a body as a def'ed function.

That being said, Lua influenced my programming style toward the extensive use of anonymous functions, and I litter my code with them. On top of that, I tend to think about map/reduce as abstract operators in ways I don't consider list comprehensions or generators, almost as If I'm deferring an implementation decision explicitly by using those operators.

TokenMacGuy