Lambda expressions
The guessing game's secret number won't always be 50. A function closest_first(guesses, secret) can take it as a parameter, but then its key function needs the secret number too. The answer is to define the key function inside closest_first. A function defined inside another one can use that function's variables and parameters, such as secret, and it exists only there, so it doesn't clutter the rest of the program:
def closest_first(guesses, secret):
def distance(guess):
return abs(guess - secret)
return sorted(guesses, key=distance)
print(closest_first([62, 41, 55, 30], 50))
print(closest_first([3, 9, 6], 7))
[55, 41, 62, 30]
[6, 9, 3]A function without a name
For a function this small, Python has a shorter way to write it: a lambda expression. It makes a function right where you need it, without def and without a name:
lambda guess: abs(guess - secret)
After the word lambda come the parameters, then a colon, then one expression. Calling the function gives the value of that expression. There's no return: the value is returned automatically. Because a function made this way has no name of its own, it's also called an anonymous function.
With a lambda, closest_first is one line long, and a simple key needs no helper function at all:
def closest_first(guesses, secret):
return sorted(guesses, key=lambda guess: abs(guess - secret))
print(closest_first([62, 41, 55, 30], 50))
names = ["bea", "Cal", "ann", "Dot"]
print(sorted(names))
print(sorted(names, key=lambda name: name.lower()))
[55, 41, 62, 30]
['Cal', 'Dot', 'ann', 'bea']
['ann', 'bea', 'Cal', 'Dot']The names show why a key is handy for words too. In Python's natural order every capital letter comes before every small letter, so Cal lands before ann. Sorting by the lowercase form of each name gives the order a person expects, and the names keep their capitals.
A lambda holds exactly one expression. Statements such as return, an if block or a loop don't fit in it:
words = ["kiwi", "fig"]
print(sorted(words, key=lambda word: return len(word)))
File "main.py", line 2
print(sorted(words, key=lambda word: return len(word)))
^^^^^^
SyntaxError: invalid syntaxLeave out the return. When the work needs more than one expression, write a function with def instead.
min and max with a key
min and max take a key too. They compare the items by the values the key returns, but they return the item itself:
>>> temperatures = [("Mon", 14), ("Tue", 9), ("Wed", 17)]
>>> max(temperatures, key=lambda day: day[1])
('Wed', 17)
>>> min(temperatures, key=lambda day: day[1])[0]
'Tue'
>>> max(["sky", "ocean", "river"], key=len)
'ocean'When several items share the best value, as ocean and river do, min and max return the first of them.