Good question. I can think of only one situation where I'd recommend using a lambda: when you need a short, single-use function embedded as part of a larger expression. Example:
a = [1, 2, 7]
b = list(map(lambda x: -x, a))
# so b = [-1, - 2, - 7]
OR, if you are insane like me and enjoy making unreadable oneliners. 😅
For every other situation, I think def is the right choice.
Think of lambdas as throwaway functions.
Let's say you have a list a = [89,17,69,5,24,48] and you want to filter all elements > 20.
You could create a standard function for that:
return n > 20
But you're probably never going to need a function over20() again. So it was kind of pointless to define it in the first place.
You can do the same with an anonymous lambda function that is defined in place and only used for this specific task:
print(list(filter(lambda x : x > 20, a)))
After that, the lambda function is done and can't be accessed anymore because it doesn't even have a name...
I have to agree with Kishalaya and Anna. Single use throw away functions like above will help keep code clean and readable. If the lambda is used more than once, it is recommended to make it a proper function.
HonFu Not really. That's a situation where I would use a lambda, e.g. sorting letters alphabetically ignoring case using
key=lambda x: x.lower()
I would search in Stackoverflow as they post really clever stuff.
I'm guilty of spamming lambdas everywhere so I feel qualified to answer :D
Basically you'd use them if you need your throwaway function twice. You can define normal functions inside functions, but `foo = lambda x: ...` is an expression so you can define lots of lambdas in little space so that's nice.
Here's an extreme example. Say you have an image on a canvas and it's bounding box is [xmin, xmax] * [ymin, ymax] and you want to move or stretch it to be at position [xmin2, xmax2] * [ymin2, ymax2]. You need a function that transforms any coordinates (x, y) to the new (x2, y2). It'd look like this:
def stretcher(xmin, xmax, ymin, ymax, xmin2, xmax2, ymin2, ymax2):
lerp = lambda min,max,min2,max2: lambda v: (v-min)/(max-min) * (max2-min2) + min2
lerpx = lerp(xmin, xmax, xmin2, xmax2)
lerpy = lerp(ymin, ymax, ymin2, ymax2)
return lambda x,y: (lerpx(x), lerpy(y))
lerp is "linear interpolation" by the way and it's used a lot (so not something I made up :)
Schindlabua it looks like you used only one named lambda. And your reason is that it saves space? Okay, I can see that! Though I'd probably still go with "def lerp():" inside strecher. The example looks fairly complicated as it is.
I also like list comprehension more! It is inspired by set builder in math which also gives us the ability to express in our natural language. Beauty of Nature.😃
Just my opinion.
I know I am jumping in between talks of legends.😊
I never understood the purpose of named lambdas. They are even taught in the tutorial and I don't know why 🤔
(and yes, I'm guilty of using them sometimes when I try to write an especially clever poser code 😭)
David Ashton nice! Using your trick filter and map can usually be replaced by list comprehensions. But sometimes I don't see another (easy) choice. For example, max, min, sort, functools.reduce, itertools.accumulate also take functions as arguments (optional for some of them).
a = [[1,2,3],[2,1,3],[2,3,1]]
let's say you want to sort by the second element of each sublist:
a = sorted(a, key = lambda e: e)
-> a will be sorted by each element's (e) 2nd element