Categories
conditional-operator operators python

Does Python have a ternary conditional operator?

7397

Is there a ternary conditional operator in Python?

9

  • 191

    In the Python 3.0 official documentation referenced in a comment above, this is referred to as “conditional_expressions” and is very cryptically defined. That documentation doesn’t even include the term “ternary”, so you would be hard-pressed to find it via Google unless you knew exactly what to look for. The version 2 documentation is somewhat more helpful and includes a link to “PEP 308”, which includes a lot of interesting historical context related to this question.

    Jan 10, 2013 at 5:57

  • 45

    “ternary” (having three inputs) is a consequential property of this impelmentation, not a defining property of the concept. eg: SQL has case [...] { when ... then ...} [ else ... ] end for a similar effect but not at all ternary.

    Dec 15, 2014 at 21:14


  • 18

    also ISO/IEC 9899 (the C programming language standard) section 6.5.15 calls it the “the condtitional operator”

    Dec 15, 2014 at 21:20

  • 17

    Wikipedia covers this thoroughly in the article “?:“.

    Jun 9, 2016 at 8:11

  • 17

    In the years since nobar’s comment the conditional expression documentation has been updated to say Conditional expressions (sometimes called a “ternary operator”)…

    Aug 15, 2018 at 13:25

8550

Yes, it was added in version 2.5. The expression syntax is:

a if condition else b

First condition is evaluated, then exactly one of either a or b is evaluated and returned based on the Boolean value of condition. If condition evaluates to True, then a is evaluated and returned but b is ignored, or else when b is evaluated and returned but a is ignored.

This allows short-circuiting because when condition is true only a is evaluated and b is not evaluated at all, but when condition is false only b is evaluated and a is not evaluated at all.

For example:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

Note that conditionals are an expression, not a statement. This means you can’t use assignment statements or pass or other statements within a conditional expression:

>>> pass if False else x = 3
  File "<stdin>", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

You can, however, use conditional expressions to assign a variable like so:

x = a if True else b

Think of the conditional expression as switching between two values. It is very useful when you’re in a ‘one value or another’ situation, but it doesn’t do much else.

If you need to use statements, you have to use a normal if statement instead of a conditional expression.


Keep in mind that it’s frowned upon by some Pythonistas for several reasons:

  • The order of the arguments is different from those of the classic condition ? a : b ternary operator from many other languages (such as C, C++, Go, Perl, Ruby, Java, JavaScript, etc.), which may lead to bugs when people unfamiliar with Python’s “surprising” behaviour use it (they may reverse the argument order).
  • Some find it “unwieldy”, since it goes contrary to the normal flow of thought (thinking of the condition first and then the effects).
  • Stylistic reasons. (Although the ‘inline if‘ can be really useful, and make your script more concise, it really does complicate your code)

If you’re having trouble remembering the order, then remember that when read aloud, you (almost) say what you mean. For example, x = 4 if b > 8 else 9 is read aloud as x will be 4 if b is greater than 8 otherwise 9.

Official documentation:

11

  • 342

    The order may seems strange for coders however f(x) = |x| = x if x > 0 else -x sounds very natural to mathematicians. You may also understand it as do A in most case, except when C then you should do B instead…

    – yota

    Jan 25, 2016 at 15:07


  • 162

    Be careful with order of operations when using this. For example, the line z = 3 + x if x < y else y. If x=2 and y=1, you might expect that to yield 4, but it would actually yield 1. z = 3 + (x if x > y else y) is the correct usage.

    Mar 6, 2016 at 9:23


  • 17

    The point was if you want to perform additional evaluations after the conditional is evaluated, like adding a value to the result, you’ll either need to add the additional expression to both sides (z = 3 + x if x < y else 3 + y), or group the conditional (z = 3 + (x if x < y else y) or z = (x if x < y else y) + 3)

    Apr 15, 2016 at 0:36

  • 7

    @MrGeek, I see what you mean, so you would basically be nesting the operations: ` “foo” if Bool else (“bar” if Bool else “foobar”) `

    – Dimesio

    Aug 11, 2017 at 0:04


  • 9

    Programmers need precise correct formulation even more than mathematician, because in mathematics there is always a resort to underlying concepts. A convincing argument is the % operator, mimicking the way “mod” is used in math would have been a disaster. So no, I don’t accept your argument. It is like adhering to imperial units. Groetjes Albert

    Jun 17, 2018 at 12:50

951

You can index into a tuple:

(falseValue, trueValue)[test]

test needs to return True or False.
It might be safer to always implement it as:

(falseValue, trueValue)[test == True]

or you can use the built-in bool() to assure a Boolean value:

(falseValue, trueValue)[bool(<expression>)]

12

  • 693

    Note that this one always evaluates everything, whereas the if/else construct only evaluates the winning expression.

    Feb 4, 2011 at 2:25

  • 140

    (lambda: print("a"), lambda: print("b"))[test==true]()

    Mar 8, 2012 at 19:31

  • 20

    It should be noted that what’s within the []s can be an arbitrary expression. Also, for safety you can explicitly test for truthiness by writing [bool(<expression>)]. The bool() function has been around since v2.2.1.

    – martineau

    May 31, 2012 at 18:20


  • 13

    I’ve done a similar trick — only once or twice, but done it — by indexing into a dictionary with True and False as the keys: {True:trueValue, False:falseValue}[test] I don’t know whether this is any less efficient, but it does at least avoid the whole “elegant” vs. “ugly” debate. There’s no ambiguity that you’re dealing with a boolean rather than an int.

    – JDM

    Mar 1, 2016 at 18:43

  • 10

419

For versions prior to 2.5, there’s the trick:

[expression] and [on_true] or [on_false]

It can give wrong results when on_true has a false Boolean value.1

Although it does have the benefit of evaluating expressions left to right, which is clearer in my opinion.

1. Is there an equivalent of C’s ”?:” ternary operator?

4

  • 76

    The remedy is to use (test and [true_value] or [false_value])[0], which avoids this trap.

    – ThomasH

    Oct 21, 2009 at 15:33

  • 8

    Ternary operator usually executes faster(sometimes by 10-25%).

    – volcano

    Jan 13, 2014 at 7:52

  • 8

    @volcano Do you have source for me?

    – OrangeTux

    Aug 5, 2014 at 12:30

  • 6

    @OrangeTux Here’s the disassembled code. Using the method ThomasH suggested would be even slower.

    – mbomb007

    Mar 19, 2018 at 20:59