93

I can find lots of stuff showing me what a lambda function is, and how the syntax works and what not. But other than the "coolness factor" (I can make a function in middle a call to another function, neat!) I haven't seen something that's overwelmingly compelling to say why I really need/want to use them.

It seems to be more of a stylistic or structual choice in most examples I've seen. And kinda breaks the "Only one correct way to do something" in python rule. How does it make my programs, more correct, more reliable, faster, or easier to understand? (Most coding standards I've seen tend to tell you to avoid overly complex statements on a single line. If it makes it easier to read break it up.)

skaffman
  • 398,947
  • 96
  • 818
  • 769
NoMoreZealots
  • 5,274
  • 7
  • 39
  • 56
  • Isn't it just the functional programming counterpart to what interfaces or function/method-signatures are in imperative programming languages..? (-> Used to specify callbacks and thus allowing one to create loosely coupled applications/software components.) – Javaguru Jul 15 '10 at 19:51
  • Lambdas are "function literals". They're useful and convenient for the same reason why list and map literals are useful (as opposed to manually doing `append` etc). If you allow for one in some circumstances, there's no logical reason to oppose the other in all circumstances. – Pavel Minaev Jul 15 '10 at 20:04
  • 2
    Possible duplicate: [Python Lambda - why?](http://stackoverflow.com/questions/890128/python-lambda-why) – David Cain Jul 18 '12 at 12:23
  • 1
    Does this answer your question? [Why are Python lambdas useful?](https://stackoverflow.com/questions/890128/why-are-python-lambdas-useful) – Josh Correia Feb 19 '20 at 17:58

16 Answers16

34

Here's a good example:

def key(x):
    return x[1]

a = [(1, 2), (3, 1), (5, 10), (11, -3)]
a.sort(key=key)

versus

a = [(1, 2), (3, 1), (5, 10), (11, -3)]
a.sort(key=lambda x: x[1])

From another angle: Lambda expressions are also known as "anonymous functions", and are very useful in certain programming paradigms, particularly functional programming, which lambda calculus provided the inspiration for.

http://en.wikipedia.org/wiki/Lambda_calculus

JAB
  • 20,783
  • 6
  • 71
  • 80
  • 8
    unrelated: you could use `operator.itemgetter(1)` instead of `lambda x: x[1]`. – jfs Jul 15 '10 at 19:58
  • sort() has supported `key` since 2.4 – Amber Jul 15 '10 at 19:59
  • 1
    @J.F. Sebastian: Though would require you to `import operator` first. @Amber: Thanks; I couldn't remember off the top of my head so just erred on the side of caution. – JAB Jul 15 '10 at 20:05
  • 4
    @J.F. Sebastian, yes, "operator.itemgetter" ,and hundreds of other short functions one would have to know by heart, each to one specific use -- or use lambda, where one can create a generic expression in place, without having to recall exactly which short function does that one job. _NOT_ using operator.itemgetter seems to justify lambda pretty well, as the OP calls for. – jsbueno Jul 15 '10 at 20:49
  • 2
    The functions in `operator` are literally a hundred times faster than their lambda counterpart. – Jochen Ritzel Jul 15 '10 at 21:54
  • @THC4k: WOW that's a pretty damn good reason NOT to use lambda functions in this case! – NoMoreZealots Jul 15 '10 at 23:29
  • 2
    @NoMore: Until you get to some more complicated things e.g. `lambda x: x[0]**2 + x[1]**2` – kennytm Jul 16 '10 at 13:20
  • @KennyTM: Or `lambda x: math.sqrt(x[0]**2 + x[1]**2)` (Though if `x` is of a custom class, you could simply define the `__abs__` method of the class such that it would do that when you use the `abs` function, in which case the key would be `abs`.) – JAB Jul 16 '10 at 13:53
  • 1
    @NoMore: The performance difference is an implementation artifact of CPython rather than being intrinsic to lambda functions or functions in general. –  Jul 17 '10 at 04:14
  • can't you just skip all that and do `a = [(1, 2), (3, 1), (5, 10), (11, -3)] a.sort(key=x[1])` i came here because I really don't get the point either – avoliva Mar 19 '14 at 21:46
  • @avoliva No, because `a.sort(key=x[1])` will assign whatever the value of `x[1]` is to the `key` argument of the sort function (which may cause an error if no variable `x` is in scope, the object does not support item access, or `x[1]` does not result in a compatible function). Even in other languages with more concise lambda function syntax, there is usually still an operator to indicate that the expression is a lambda (e.g. `->` in Scala, CoffeeScript, etc.). – JAB Mar 20 '14 at 12:49
21

The syntax is more concise in certain situations, mostly when dealing with map et al.

map(lambda x: x * 2, [1,2,3,4])

seems better to me than:

def double(x):
    return x * 2

map(double, [1,2,3,4])

I think the lambda is a better choice in this situation because the def double seems almost disconnected from the map that is using it. Plus, I guess it has the added benefit that the function gets thrown away when you are done.

There is one downside to lambda which limits its usefulness in Python, in my opinion: lambdas can have only one expression (i.e., you can't have multiple lines). It just can't work in a language that forces whitespace.

Plus, whenever I use lambda I feel awesome.

Donald Miner
  • 38,889
  • 8
  • 95
  • 118
  • 12
    list comprehension might be more suitable in this case `[x*2 for x in [1,2,3,4]]`. – jfs Jul 15 '10 at 20:04
  • 2
    I don't know python (although it's definitely high on my to-learn list), so I'm wondering... is there really a good reason multiple lines aren't allowed for a lambda-expression? Why can't the body of the lambda-expression just be one tab further to the right or something? – Cam Jul 15 '10 at 20:09
  • 1
    @incrediman: if you're writing multiple lines of lambda, the idea is that you might be better off with a 'proper' function – MikeD Jul 15 '10 at 20:13
  • 5
    Guido's blog post about multi-line lambdas, and other things: http://www.artima.com/weblogs/viewpost.jsp?thread=147358 – Donald Miner Jul 15 '10 at 20:14
  • 2
    @incrediman - at that point there is no difference between a lambda and a function - a function is still an object that can be referred to by name, having a multi-line lambda would be a def. – Matthew J Morrison Jul 15 '10 at 20:14
  • 1
    I don't *know* but I would bet to discourage a more liberal use of lambdas and/or because it would be a pain to parse. – Wayne Werner Jul 15 '10 at 20:15
  • 4
    `map((2).__mul__, [1,2,3,4])`. – kennytm Jul 16 '10 at 13:22
  • CoffeeScript does lambdas with multiple lines just fine – phaux Oct 14 '16 at 11:20
17

For me it's a matter of the expressiveness of the code. When writing code that people will have to support, that code should tell a story in as concise and easy to understand manner as possible. Sometimes the lambda expression is more complicated, other times it more directly tells what that line or block of code is doing. Use judgment when writing.

Think of it like structuring a sentence. What are the important parts (nouns and verbs vs. objects and methods, etc.) and how should they be ordered for that line or block of code to convey what it's doing intuitively.

David
  • 208,112
  • 36
  • 198
  • 279
  • 4
    This is wonderful: "code should tell a story in as concise and easy to understand manner as possible...Think of it like structuring a sentence..." -- I am going to use this on the next course I teach, if you don't mind! – Sanjay Manohar Apr 15 '15 at 18:48
  • This is the best answer. Sometimes lambda is right and sometimes not, but the reason is for readability and support. – Steven P Sep 28 '21 at 01:11
13

Lambda functions are most useful in things like callback functions, or places in which you need a throwaway function. JAB's example is perfect - It would be better accompanied by the keyword argument key, but it still provides useful information.

When

def key(x):
    return x[1]

appears 300 lines away from

[(1,2), (3,1), (5,10), (11,-3)].sort(key)

what does key do? There's really no indication. You might have some sort of guess, especially if you're familiar with the function, but usually it requires going back to look. OTOH,

[(1,2), (3,1), (5,10), (11,-3)].sort(lambda x: x[1])

tells you a lot more.

  1. Sort takes a function as an argument
  2. That function takes 1 parameter (and "returns" a result)
  3. I'm trying to sort this list by the 2nd value of each of the elements of the list
  4. (If the list were a variable so you couldn't see the values) this logic expects the list to have at least 2 elements in it.

There's probably some more information, but already that's a tremendous amount that you get just by using an anonymous lambda function instead of a named function.

Plus it doesn't pollute your namespace ;)

Wayne Werner
  • 49,299
  • 29
  • 200
  • 290
  • My initial example wasn't quite perfect, as in Python 3 you have to use the key as a keyword argument (resulting in a TypeError being raised if you leave `key=` out). I also forgot that `sort`, which does an in-place sort, doesn't actually return the object it sorts, so you have to use it on a mutable sequence that's already been assigned to a variable. – JAB Jul 15 '10 at 20:07
  • Error, you cannot pass directly a function to sort like this, you need to use like sort(key=key) or sort(key=lambda function) – DevC May 19 '14 at 10:13
  • This code is broken in both python 2 (first argument is `cmp`, not `key`) and in python 3 (where `sort` doesn't accept any positional arguments). In both cases you need to use `...sort(key=...)` instead. – 6502 Dec 01 '18 at 08:12
10

Yes, you're right — it is a structural choice. It probably does not make your programs more correct by just using lambda expressions. Nor does it make them more reliable, and this has nothing to do with speed.

It is only about flexibility and the power of expression. Like list comprehension. You can do most of that defining named functions (possibly polluting namespace, but that's again purely stylistic issue).

It can aid to readability by the fact, that you do not have to define a separate named function, that someone else will have to find, read and understand that all it does is to call a method blah() on its argument.

It may be much more interesting when you use it to write functions that create and return other functions, where what exactly those functions do, depends on their arguments. This may be a very concise and readable way of parameterizing your code behaviour. You can just express more interesting ideas.

But that is still a structural choice. You can do that otherwise. But the same goes for object oriented programming ;)

Piotr Kalinowski
  • 2,272
  • 1
  • 14
  • 15
7

Lambda, while useful in certain situations, has a large potential for abuse. lambda's almost always make code more difficult to read. And while it might feel satisfying to fit all your code onto a single line, it will suck for the next person who has to read your code.

Direct from PEP8

"One of Guido's key insights is that code is read much more often than it is written."

6

Ignore for a moment the detail that it's specifically anonymous functions we're talking about. functions, including anonymous ones, are assignable quantities (almost, but not really, values) in Python. an expression like

map(lambda y: y * -1, range(0, 10))

explicitly mentions four anonymous quantities: -1, 0, 10 and the result of the lambda operator, plus the implied result of the map call. it's possible to create values of anonymous types in some languages. so ignore the superficial difference between functions and numbers. the question when to use an anonymous function as opposed to a named one is similar to a question of when to put a naked number literal in the code and when to declare a TIMES_I_WISHED_I_HAD_A_PONY or BUFFER_SIZE beforehand. there are times when it's appropriate to use a (numeric, string or function) literal, and there are times when it's more appropriate to name such a thing and refer to it through its name.

see eg. Allen Holub's provocative, thought-or-anger-provoking book on Design Patterns in Java; he uses anonymous classes quite a bit.

just somebody
  • 18,602
  • 6
  • 51
  • 60
  • 1
    This is a very good answer; as opposed to simply providing an example. Not that those examples were very helpful for understanding when lambda functions are useful. – AVProgrammer Aug 04 '12 at 22:01
5

It is definitely true that abusing lambda functions often leads to bad and hard-to-read code. On the other hand, when used accurately, it does the opposite. There are already great answers in this thread, but one example I have come across is:

def power(n):
    return lambda x: x**n

square = power(2)
cubic = power(3)
quadruple = power(4)

print(square(10)) # 100
print(cubic(10)) # 1000
print(quadruple(10)) # 10000

This simplified case could be rewritten in many other ways without the use of lambda. Still, one can infer how lambda functions can increase readability and code reuse in perhaps more complex cases and functions with this example.

Uzay Macar
  • 254
  • 4
  • 13
3

Lambdas are anonymous functions (function with no name) that can be assigned to a variable or that can be passed as an argument to another function. The usefulness of lambda will be realized when you need a small piece of function that will be run once in a while or just once. Instead of writing the function in global scope or including it as part of your main program you can toss around few lines of code when needed to a variable or another function. Also when you pass the function as an argument to another function during the function call you can change the argument (the anonymous function) making the function itself dynamic. Suppose if the anonymous function uses variables outside its scope it is called closure. This is useful in callback functions.

2

Lambdas are objects, not methods, and they cannot be invoked in the same way that methods are. for e.g

succ = ->(x){ x+1 }

succ mow holds a Proc object, which we can use like any other:

succ.call(2)

gives us an output = 3

Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58
Akash Soti
  • 583
  • 2
  • 7
  • 13
2

One use of lambda function which I have learned, and where is not other good alternative or at least looks for me best is as default action in function parameter by

parameter=lambda x: x

This returns the value without change, but you can supply one function optionally to perform a transformation or action (like printing the answer, not only returning)

Also often it is useful to use in sorting as key:

key=lambda x: x[field]

The effect is to sort by fieldth (zero based remember) element of each item in sequence. For reversing you do not need lambda as it is clearer to use

reverse=True

Often it is almost as easy to do new real function and use that instead of lambda. If people has studied much Lisp or other functional programming, they also have natural tendency to use lambda function as in Lisp the function definitions are handled by lambda calculus.

Tony Veijalainen
  • 5,447
  • 23
  • 31
1

I want to point out one situation other than list-processing where the lambda functions seems the best choice:

from tkinter import *
from tkinter import ttk        
def callback(arg):
    print(arg)
    pass
root = Tk()
ttk.Button(root, text = 'Button1', command = lambda: callback('Button 1 clicked')).pack()
root.mainloop()

And if we drop lambda function here, the callback may only execute the callback once.

ttk.Button(root, text = 'Button1', command = callback('Button1 clicked')).pack()
Henry.L
  • 219
  • 5
  • 14
1

Another point is that python does not have switch statements. Combining lambdas with dicts can be an effective alternative. e.g.:

switch = {
 '1': lambda x: x+1, 
 '2': lambda x: x+2,
 '3': lambda x: x+3
}

x = starting_val
ans = expression
new_ans = switch[ans](x)
zzu
  • 258
  • 1
  • 11
0

In some cases it is much more clear to express something simple as a lambda. Consider regular sorting vs. reverse sorting for example:

some_list = [2, 1, 3]
print sorted(some_list)
print sorted(some_list, lambda a, b: -cmp(a, b))

For the latter case writing a separate full-fledged function just to return a -cmp(a, b) would create more misunderstanding then a lambda.

abbot
  • 27,408
  • 6
  • 54
  • 57
  • 3
    unrelated: you could use `sorted(..., reverse=True)` instead of `sorted(..., lambda a,b: cmp(b,a))` – jfs Jul 15 '10 at 20:02
  • Absolutely not unrelated and far more understandable than what the answer suggests. – KevLoughrey Sep 19 '19 at 20:42
  • Please consider the age of the question and answer. A significan share of my Python experience at that point was coming from Python 2.3 era for ${reasons}, the reverse argument (and the sorted function) were added in 2.4. – abbot Oct 06 '19 at 22:46
0

Lambdas allow you to create functions on the fly. Most of the examples I've seen don't do much more than create a function with parameters passed at the time of creation rather than execution. Or they simplify the code by not requiring a formal declaration of the function ahead of use.

A more interesting use would be to dynamically construct a python function to evaluate a mathematical expression that isn't known until run time (user input). Once created, that function can be called repeatedly with different arguments to evaluate the expression (say you wanted to plot it). That may even be a poor example given eval(). This type of use is where the "real" power is - in dynamically creating more complex code, rather than the simple examples you often see which are not much more than nice (source) code size reductions.

phkahler
  • 5,687
  • 1
  • 23
  • 31
  • 6
    Lambdas do not allow you to do anything that a normal function definition cannot do equally well. As the other answers say you might prefer a lambda because it makes the code clearer, but an ordinary 'def' is exactly as dynamic as a lambda. – Duncan Jul 15 '10 at 20:40
  • 1
    No sir, it is not the same. You can define a function to compute x+1, or you can also use a lambda to create a function to compute x+n and pass 1 in for n. You can also use the same lambda to create a bunch of funtions that return x plus different values. The point is that part the some of the function is determined at run time in a way that can't be done with a normal def. Everyone seems to think it's a nice shorthand, when it really can do more. – phkahler Jul 16 '10 at 17:57
-2

you master lambda, you master shortcuts in python.Here is why:

data=[(lambda x:x.text)(x.extract())  for x in soup.findAll('p') ]
                  ^1           ^2         ^3           ^4

here we can see 4 parts of the list comprehension:

  • 1: i finally want this
  • 2: x.extract will perform some operation on x, here it pop the element from soup
  • 3: x is the list iterable which is passed to the input of lambda at 2 along with extract operation
  • 4: some arbitary list

i had found no other way to use 2 statements in lambda, but with this kind of pipe-lining we can exploit the infinite potential of lambda.

Edit: as pointed out in the comments, by juanpa, its completely fine to use x.extract().text but the point was explaining the use of lambda pipe, ie passing the output of lambda1 as input to lambda2. via (lambda1 y:g(x))(lambda2 x:f(x))

nikhil swami
  • 2,360
  • 5
  • 15
  • This is nonsensical. You should just do `x.extract().text` – juanpa.arrivillaga Sep 20 '20 at 06:16
  • i thought of putting `x.extract().text()` but the point was explaining the "lambda Pipe". since not all classes have methods which can return a copy of the properties. BS4 has the option to do so, but such functionality is usually not available. – nikhil swami Sep 20 '20 at 15:12