Well, writing
key = lambda x, y, z: expression(x, y, z)
has the same effect as
def dummy(x, y, z):
return expression(x, y, z)
key = dummy
It means that lambda is only a way to write small, anonymous functions. The main restriction is that the body of a lambda form is not a sequence of statements but a single python expression (note that the keyword 'return' does not appear in the lambda form).
Lambda forms come from a branch of mathematical logic called "lambda calculus" which studies the logical consequences of an abstract functional language. These lambda forms are the basis of most so-called functional programming languages and that's where python borrowed the construct (together with list comprehensions and generators).
I tend to believe that lambda forms are not very useful in python. Writing a genuine small function is not less efficient and it is more flexible (it leaves the possibility to add statements in the body, if only a print or assert statement for debugging).
Gribouillis
Posting Maven
3,101 posts since Jul 2008
Reputation Points: 1,130
Solved Threads: 761
Skill Endorsements: 11
I disagree. lambda functions are very handy, for example -
>>> numbers = [1,2,3,4,5]
>>> map(lambda x:x+1, numbers)
[2, 3, 4, 5, 6]
>>> reduce(lambda x,y: x+y, numbers)
15
>>> filter(lambda x: x%2==0, numbers)
[2, 4]
>>> def a(x):
... return lambda y: y+x
...
>>> add_three = a(3)
>>> add_three(1)
4
>>> sorted(numbers,key=lambda x: x%2)
[2, 4, 1, 3, 5]
It is also _very_ heavily used in GUI development, as events (scrolling, etc). Of course, if you can use a list comp instead of these, then do so. They're usually more readable.
IMO, if you assign lambda to something, it shouldn't be used, instead you should define a method using def. In production code, use it where it's useful, but try to use it as little as possible (don't assign it to a name)
Enalicho
Junior Poster in Training
62 posts since Aug 2011
Reputation Points: 28
Solved Threads: 13
Skill Endorsements: 0
Lambda is usefull, sometimes it is nicer to replace it with proper function or use functools.partial instead.
Say if you wanted to sort strings so that the sort is case insensitive and words starting with x come first instead of normal place (but x inside the string behave normally)
def xfirst_key(xword):
xword = xword.lower()
return (not xword.startswith('x'), xword)
notinorder = ['mix', 'xyz', '', 'Apple', 'Xanadu', 'aardvark', 'min']
print(sorted(notinorder, key=lambda x: (not x.startswith(('x','X')), x.lower())))
print(sorted(notinorder, key=lambda x: (x and x[0] not in 'xX', x.lower())))
print(sorted(notinorder, key=xfirst_key))
pyTony
pyMod
6,330 posts since Apr 2010
Reputation Points: 879
Solved Threads: 989
Skill Endorsements: 27
Lambda is usefull, sometimes it is nicer to replace it with proper function or use functools.partial instead.
Say if you wanted to sort strings so that the sort is case insensitive and words starting with x come first instead of normal place (but x inside the string behave normally)
def xfirst_key(xword):
xword = xword.lower()
return (not xword.startswith('x'), xword)
notinorder = ['mix', 'xyz', '', 'Apple', 'Xanadu', 'aardvark', 'min']
print(sorted(notinorder, key=lambda x: (not x.startswith(('x','X')), x.lower())))
print(sorted(notinorder, key=lambda x: (x and x[0] not in 'xX', x.lower())))
print(sorted(notinorder, key=xfirst_key))
It's a typical example. I think the last version is far better. Lambda is cryptic.
Also, about
sorted(numbers,key=lambda x: x%2)
it's very difficult to guess what the sort does if you didn't write this code yourself. I prefer
def even_first_score(x):
return x % 2
print( sorted(numbers, key = even_first_score) )
or a similar name.
Also note that map, reduce and filter are condemned by Van Rossum himself (ever read this www.python.org/doc/essays/ppt/regrets/PythonRegrets.pdf ?)
Gribouillis
Posting Maven
3,101 posts since Jul 2008
Reputation Points: 1,130
Solved Threads: 761
Skill Endorsements: 11
Here the example with functools.partial examples for general function and button call backs added. Clear names are absolute must, but sometimes descriptive docstring is better than too long name, which is still unclear. Notice that in ide like IDLE, you get tooltip of first line of docstring, when you type functions name.
from functools import partial
import string
from Tkinter import *
def exceptions_key(word, exceptional):
""" exceptional first, then others, first empty string, however.
"""
word = word.lower()
order = exceptional.lower()+ ''.join(c for c in string.lowercase)
return (not word and -1) or order.find(word[0]), word
def xfirst_key(xword):
xword = xword.lower()
return (not xword.startswith('x'), xword)
def number_to_title(root, number):
root.title('%s pushed' % number)
notinorder = ['mix', 'xyz', '', 'Apple', 'Xanadu', 'aardvark', 'min', 'sun']
print(sorted(notinorder, key=lambda x: (not x.startswith(('x','X')), x.lower())))
print(sorted(notinorder, key=lambda x: (x and x[0] not in 'xX', x.lower())))
print(sorted(notinorder, key=xfirst_key))
# both x and m exceptions
print(sorted(notinorder, key=partial(exceptions_key, exceptional='xm')))
root = Tk()
for i in range(1,20):
Button(text=str(i),
command=partial(number_to_title,
root=root, number=i)).pack(side=LEFT, padx=4, pady=4)
root.mainloop()
pyTony
pyMod
6,330 posts since Apr 2010
Reputation Points: 879
Solved Threads: 989
Skill Endorsements: 27