We're a community of 1.1M IT Pros here for help, advice, solutions, professional growth and fun. Join us!
1,080,521 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Start New Discussion Reply to this Discussion

What the Lambda?

so I recently wrote a function that sorted using the last value in a tuple. Obviously this couldn't be done simply say sorted(tuples, key=tuples[-1]) because that is not a "legal" call. However I did run across, while trying to figure out how to make things like this work, the utilization of lambda so the code became.

def sort_last(tuples):
    x=sorted(tuples, key=lambda tuples: tuples[-1])
    return(x)

The code runs correctly and, that's all well and good, but I don't understand why lambda tuples"or any given var for that matter":. makes this possible. Can someone explain this to me in a way I'll understand so that I can utilize the principle to its maximum potential?
p.s. I have essentially no calculus experience.

5
Contributors
6
Replies
11 Hours
Discussion Span
1 Year Ago
Last Updated
7
Views
pyguy62
Posting Whiz
353 posts since Aug 2011
Reputation Points: 34
Solved Threads: 19
Skill Endorsements: 0

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
Moderator
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
Moderator
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
Moderator
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
Moderator
6,330 posts since Apr 2010
Reputation Points: 879
Solved Threads: 989
Skill Endorsements: 27

Fresh presentation about lambda expressions: Newbie Nugget: Lambda Expressions

nabla2
Newbie Poster
12 posts since Aug 2011
Reputation Points: 26
Solved Threads: 4
Skill Endorsements: 0

This article has been dead for over three months: Start a new discussion instead

Post: Markdown Syntax: Formatting Help
 
You
View similar articles that have also been tagged:
 
© 2013 DaniWeb® LLC
Page generated in 0.0753 seconds using 2.66MB