Python's "if" is a _statement_, and there is no conditional _operator_ (like C's "a?b:c" ternary) that we could use where expressions are needed (lambdas, etc); however, with some due care, equivalents can easily be coded.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # with an if-else:
def foobar(whop):
if whop>"pohrw": return "foox"
else: return "barbar"
# the equivalent in expression-form:
foobar = lambda whop: ("foox", "barbar")[whop<="pohrw"]
# in general, we MUST ensure the 'conditional' turns
# into a 0 or 1 -- the 'not' operator is handy for that:
# not needed in the if-else case:
def plok(anything):
if anything: return "xok"
else: return "plik"
# but necessary when moving to expression-form:
plok = lambda anything: ("xok", "plik")[not anything]
# sometimes we need the shortcircuiting operators, 'and'
# and 'or', to avoid evaluating an incorrect expression:
def zod(plud):
if plud: return 16+4/plud
else: return 23
# must use and & or, NOT (...)[], as the operator-idiom:
zod = lambda plud: (plud and (16+4/plud)) or 23
# but if (16+4/plud)==0 [plud == -0.25] this erroneously
# returns 23! A full solution ALSO requires indexing:
zod = lambda plud: ((plud and [16+4/plud]) or [23])[0]
# since the non-empty list [16+4/plud] is always 'true'
|
Python lacks a ternary operator like C's cond?iftrue:iffalse -- and generally it's all the better off for that; in the rare cases where it's needed (because 'if-else' is a _statement_, and we need something that fits into an _expression_ instead), we can synthesize it with indexing, or, when shortcircuiting is needed to avoid evaluating an incorrect expression, with the 'and' and 'or' operators.
The short-circuit case can be tricky indeed, because the 'iftrue' part could be 0 (or some other 'false' value); wrapping iftrue and iffalse up into one-element (thus non-empty, thus 'true') lists, and indexing the result, avoids this further risk of anomaly.
Such tricky subtleness can hardly ever meet the prime guideline of programming, "Do the Simplest Thing that Can Possibly Work", particularly because it's likely to be conjoined with 'lambda' or other subtlety-prone constructs. 99.44 times out of 100, you will be better off passing a named local function, with a plain if/else statement. But, for the remaining 56 cases out of 10,000, these idioms can still be useful.
"conditionals" in expressions. Here's a slight variant that may or may not have a different appeal. As with the C version, a ? b : c, and the final version here, it evaluates only one of b and c, depending on the value of a, and then it picks that one, making no assumptions about its truth value:
[a and b, not a and c][not a]
this works too... a ? b : c <==> (a and (lambda:b) or (lambda:c))()
sugar for a?b:c - cond[a:b:c]. Can also abuse slice for syntax that looks more suggestive of a?b:c
3
2
Where cond previously defined by:
Could probably also do something like:
Q(a)[b:c]
In general __getitem__ and slice objects can be abused to define any ternary or quad(?) operations using [::] syntax.
Not short circuiting. Unfortunately, Doug, your solution is not short circuiting. So it really doesn't meet the requirements. I'll also throw out that this is exactly the kind of abuse seen in C++ which made me decide that I personally don't like operator overloading. It encourages programmers to invent their own strange syntax for their libraries.
Newbie question - why can't I do this? [falseValue, trueValue][conditionIndex]. [falseValue, trueValue][conditionIndex]
should do the ternary operator - and it works like a switch as well... no?
Newbie question - why can't I do this? [falseValue, trueValue][conditionIndex]. [falseValue, trueValue][conditionIndex]
should do the ternary operator - and it works like a switch as well... no?
or equivalents
{True: 'trueValue', False: 'falseValue'} [3>4]
('falseValue', 'trueValue')[conditionIndex]
Re: why can't I do this? [falseValue, trueValue][conditionIndex]. The problem is when you use [falseValue, trueValue] syntax, all items of the list are executed. For example:
It reads:
Another example of and-or:
It reads:
Thus it's different.
This appears to work everywhere. This needs a bit of defensive programming in cases where exceptions may arise (like division by zero), but, here it is, with examples:
(comment continued...)
(...continued from previous comment)
</pre>
The above which(a,b,c) evaluates all arguments.
"a if b else c" is in python 2.5. See http://mail.python.org/pipermail/python-dev/2005-September/056846.html