Reputation: 41428
I have to bear with a Python version < 2.5 (it is 2.4.3 for specifics)
It seems that ternary operators were introduces in Python starting at 2.5. For those who are not familiar, ternary operators in Python >= 2.5 look like this:
def do_ternary(flag):
return "foo" if flag else "bar"
I'd like to know some solutions to emulate this in the early versions of Python. I can for sure do it with if ... else, but I'm looking for something more pythonic that I wouldn't be ashamed to put on some production-level code :)
Thanks for the help !
Upvotes: 2
Views: 1230
Reputation: 41428
Actually I was looking on the web and found what seems like a really elegant pythonic solution:
def _if(test):
return lambda alternative: \
lambda result: \
[delay(result), delay(alternative)][not not test]()
def delay(f):
if callable(f): return f
else: return lambda: f
>>> fact = lambda n: _if (n <= 1) (1) (lambda: n * fact(n-1))
>>> fact(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000L
What do you think about this one? It looks pretty clean and easy to read in my opinion.
Upvotes: 5
Reputation: 17505
A common trick is to use list-indexing, since False
/True
turn into 0
/1
when an integer is required. In case the test may be false-y or truth-y rather than a boolean, its good practice to first ensure the test is a boolean:
["bar", "foo"][bool(flag)]
will produce the same output as the ternary in your question.
Edit: Dougal points out that this may behave slightly differently from the ternary, because both the true and false values will be evaluated, which may have side-effects.
Upvotes: 4
Reputation: 156158
the correct way that does all of the things that if/else
does is:
(condition and (yes_value,) or (no_value,))[0]
which does both the short circuiting and resolves the problem of when yes_value
is itself falsey. Obviously, if you have reason to avoid this cludge, just do that; in your example, both conditions are constant expressions, so you can do:
{True: yes_value, False: no_value}[bool(condition)]
or more tersely:
(no_value, yes_value)[condition]
if you do need the short circut, but you're confident that the yes_value is never falsey, you can trim out the tuple:
condition and yes_value or no_value
but that's probably only valid when the yes_value
is actually a constant. If none of these suit your tastes or needs, just use a plain-ol if:
statement, with an intermediate variable
if condition:
result = yes_value
else:
result = no_value
Upvotes: 8
Reputation: 89007
The classic 'trick' used to do this is:
test and true_value or false_value
This works as and
and or
work like so in python:
x or y -> if x is false, then y, else x
x and y -> if x is false, then x, else y
This means that we get the roughly the same result - so long as true_value
evaluates to True
- so, for example, the following would not work:
flag and [] or "bar"
As []
evaluates to False
.
I'd still argue that this is less readable than simply using an if/else block, as unless you are familiar with it, it's unclear.
So I'd advise using:
if test:
return true_value
else:
return false_value
(replacing return with assignment or whatever where needed).
Upvotes: 1