There are several different answers I can give here, from your specific question to more general concerns. So from most specific to most general:
Q. Can you put multiple statements in a lambda?
A. No. But you don't actually need to use a lambda. You can put the statements in a def instead. i.e.:
def second_lowest(l):
l.sort()
return l[1]
map(second_lowest, lst)
Q. Can you get the second lowest item from a lambda by sorting the list?
A. Yes. As alex's answer points out, sorted() is a version of sort that creates a new list, rather than sorting in-place, and can be chained. Note that this is probably what you should be using - it's bad practice for your map to have side effects on the original list.
Q. How should I get the second lowest item from each list in a sequence of lists?
A. sorted(l)[1] is not actually the best way for this. It has O(N log(N)) complexity, while an O(n) solution exists. This can be found in the heapq module.
>>> import heapq
>>> l = [5,2,6,8,3,5]
>>> heapq.nsmallest(l, 2)
[2, 3]
So just use:
map(lambda x: heapq.nsmallest(x,2)[1], list_of_lists)
It's also usually considered clearer to use a list comprehension, which avoids the lambda altogether:
[heapq.nsmallest(x,2)[1] for x in list_of_lists]
Answer from Brian on Stack OverflowThere are several different answers I can give here, from your specific question to more general concerns. So from most specific to most general:
Q. Can you put multiple statements in a lambda?
A. No. But you don't actually need to use a lambda. You can put the statements in a def instead. i.e.:
def second_lowest(l):
l.sort()
return l[1]
map(second_lowest, lst)
Q. Can you get the second lowest item from a lambda by sorting the list?
A. Yes. As alex's answer points out, sorted() is a version of sort that creates a new list, rather than sorting in-place, and can be chained. Note that this is probably what you should be using - it's bad practice for your map to have side effects on the original list.
Q. How should I get the second lowest item from each list in a sequence of lists?
A. sorted(l)[1] is not actually the best way for this. It has O(N log(N)) complexity, while an O(n) solution exists. This can be found in the heapq module.
>>> import heapq
>>> l = [5,2,6,8,3,5]
>>> heapq.nsmallest(l, 2)
[2, 3]
So just use:
map(lambda x: heapq.nsmallest(x,2)[1], list_of_lists)
It's also usually considered clearer to use a list comprehension, which avoids the lambda altogether:
[heapq.nsmallest(x,2)[1] for x in list_of_lists]
Putting the expressions in a list may simulate multiple expressions:
E.g.:
lambda x: [f1(x), f2(x), f3(x), x+1]
This will not work with statements.
sys.stdout.write("second") is not part of the lambda.
'second' is always printed even if you don't call X. In other words calling X only prints 'first'.
Your code can be rewritten as;
import sys
X = lambda: sys.stdout.write('first')
sys.stdout.write("second")
print X()
If you want two statements executed by the lambda place them in a tuple;
lambda: (sys.stdout.write('first'),sys.stdout.write("second"))
The syntax for lambda is:
lambda <args>: <expression>
where <expression> must be a single expression. It cannot be a statement, or multiple statements, or multiple expressions separated by ;.
What happens in your code is that lambda has higher priority over ;, so that gets parsed as: X = lambda: sys.stdout.write('first') followed by sys.stdout.write("second"). Adding parentheses around sys.stdout.write('first') ; sys.stdout.write("second") would not work and produce a syntax error.
My trick to do multiple things inside a lambda is:
f = lambda: [None, sys.stdout.write('first'), sys.stdout.write("second")][0]
and the other one:
f = lambda: [None, sys.stdout.write("..."), sys.exit(0)][0]
However that kind of defeats the purpose of a lambda function, which is to do something short and really simple.
I guess that would still be OK in your specific example, but kind of looks like a hack.
Can I have a python lambda with more than one statement?
Simple multi-line lambda syntax - Ideas - Discussions on Python.org
One Lambda function that does many things or One thing per lambda
multi line lambdas, as god intended
Guido van van Rossum answered it himself:
But such solutions often lack "Pythonicity" -- that elusive trait of a good Python feature. It's impossible to express Pythonicity as a hard constraint. Even the Zen of Python doesn't translate into a simple test of Pythonicity...
In the example above, it's easy to find the Achilles heel of the proposed solution: the double colon, while indeed syntactically unambiguous (one of the "puzzle constraints"), is completely arbitrary and doesn't resemble anything else in Python...
But I'm rejecting that too, because in the end (and this is where I admit to unintentionally misleading the submitter) I find any solution unacceptable that embeds an indentation-based block in the middle of an expression. Since I find alternative syntax for statement grouping (e.g. braces or begin/end keywords) equally unacceptable, this pretty much makes a multi-line lambda an unsolvable puzzle.
http://www.artima.com/weblogs/viewpost.jsp?thread=147358
Basically, he says that although a solution is possible, it's not congruent with how Python is.
it's perfectly fine to do a multi line lambda in python: see
>>> f = lambda x: (
... x**x)
>>> f
<function <lambda> at 0x7f95d8f85488>
>>> f(3)
27
the real lambda limitation is the fact that lambda must be a single expression; it can't contains keyword (like python2's print or return).
GvR choose to do so to limit the size of the lambda, as they normally are used as parameters.
If you want a real function, use def