tags:

views:

929

answers:

4

In python 2.6, I want to do:

f = lambda x: if x==2 print x else raise Exception()
f(2) #should print "2"
f(3) #should throw an exception

This clearly isn't the syntax. Is it possible to perform an if in lambda and if so how to do it?

thanks

+1  A: 

Lambdas in Python are fairly restrictive with regard to what you're allowed to use. Specifically, you can't have any keywords (except for operators like and, not, or, etc) in their body.

So, there's no way you could use a lambda for your example (because you can't use raise), but if you're willing to concede on that… You could use:

f = lambda x: x == 2 and x or None
David Wolever
+10  A: 

why don't you just define a function?

def f(x):
    if x == 2:
        print(x)
    else:
        raise ValueError

there really is no justification to use lambda in this case.

SilentGhost
`print` is not a function in 2.6 yet. :)
Lukáš Lalinský
+1. And if the OP wants less code, then he can flip the condition (`if x != 2`) and leave out the `else`.
Stephan202
@Lukáš Lalinský: it still works in 2.x. it will be treated as a pair of redundant parentheses
newacct
You don't know his actual use case, so there's no way you can say there's no reason to use a lambda.
Glenn Maynard
@Glenn Maynard: There's almost no reason to use a lambda, period. Assigning a lambda to a variable -- as a stand-in for `def` -- is generally a Very Bad Idea (tm). Just use a `def` so mere mortal programmers can read, interpret, understand and maintain it.
S.Lott
There are plenty of legitimate uses of lambdas. If you can't think of any, then that's not lambda's fault. (I'm not a fan of the syntax itself, of course--it's a clumsy workaround for the fact that Python's poorly-conceived indentation syntax can't handle inline functions like normal languages.)
Glenn Maynard
+7  A: 

The syntax you're looking for:

lambda x: True if x % 2 == 0 else False

But you can't use print or raise in a lambda.

Robert Rossney
in python 3, you can use print
recursive
f=lambda x: x%2==0 would also work.
unutbu
Sure, but the question was "how do I use `if` in a lambda?" not "what's the best way to write a lambda that returns True if a number is even?"
Robert Rossney
-1: `True if expression else False` is deeply horrifying.
S.Lott
It's a horrible syntax--easily the worst Python language construct, approaching Perl levels of absurdity in its out-of-order evaluation--but it's what was asked for. You're seriously voting down answers for being correct?
Glenn Maynard
@Glenn Maynard: it's not the syntax that horrifying. It's any expression of the form `True if expression else False`. The `if` construct is totally redundant and therefore deeply and horrifyingly confusing. It's as bad as the statement form: `if expression: return True`.
S.Lott
Well, it's certainly confusing if an otherwise-smart person can't realize that it's the correct answer to the question that was asked, which was entirely about syntax. I regret that the example I has apparently given you the horrors. Feel free to construct a more appropriate one.
Robert Rossney
@Robert Rossney: the trivial redundancy of `True if expression else False` is horrifying. The correct form is shown by @unutbu: `lambda x: x%2==0`. There's no horrifying `True if True else False` in that formulation.
S.Lott
It's the correct answer to the question "How do I write a lambda function that tells me if a number is even?" It is not, however, a correct answer to the question that the OP originally asked. However much you don't like the example I contrived, my post *does*, in fact, clearly answer the OP's question.
Robert Rossney
It's painfully obvious that anyone suggesting "x%2==0"--or voting up a comment recommending it, which makes at least seven people--didn't even read the original question.
Glenn Maynard
A: 

You can easily raise an exception in a lambda, if that's what you really want to do.

def Raise(exception):
    raise exception
x = lambda y: 1 if y < 2 else Raise(ValueError("invalid value"))

Is this a good idea? My instinct in general is to leave the error reporting out of lambdas; let it have a value of None and raise the error in the caller. I don't think this is inherently evil, though--I consider the "y if x else z" syntax itself worse--just make sure you're not trying to stuff too much into a lambda body.

Glenn Maynard
Raising it in a caller is probably the prettier method if you ask me.
Dominic Bou-Samra
Possibly, but it depends heavily on the particular case. Of course, you can also decorate the lambda after creating it. `x = RaiseValueErrorOnNone(x)`, again, depending on the case.
Glenn Maynard