Python ternary operator

Today’s Python discovery:

Python doesn’t have the C style ?: ternary operator (e.g.: cond ? valueIfTrue : valueIfFalse).

But as of Python 2.5 it has a ternary operator with its own syntax: value_when_true if condition else value_when_false

For example:

>>> 'a' if 1 == 1 else 'b'
'a'
>>> 'a' if 1 == 0 else 'b'
'b'

This is actually clearer and more Pythonic than that ?:

Unfortunately, for Python versions < 2.5, you don’t have this. I’ve seen people use: (condition and [value_when_true] or [value_when_false])[0]

IMHO, this is clever – in a bad way. Yuck. Personally, I think I’d rather just do:


def if_cond_val1_else_val2(cond, val1, val2): 
   if cond: return val1
   else: return val2

This adds 3 lines to your program (or 1 if you stick it in a module that you import from your programs) and won’t cause your colleagues to hate you.

10 thoughts on “Python ternary operator

  1. Your ifelse function is substantially different when it comes to evaluating val1 and val2. Both of them are evaluated no matter what, which might be expensive.

    The and/or hack has almost-correct evaluation, but with the flaw that [value when false] gets chosen if [value when true] happens to be itself false. The other py2.4- version is like this:

    print “%d %s” % (x, [‘egg’, ‘eggs’][x > 1])

    Too much evaluation, but mostly readable and without the subtle flaw of the and/or version.

  2. Oops- not “x > 1” but “x != 1”. That way we can have “0 eggs”.

  3. I think the ternary operator evaluation is better translated by this:

    eggs = 10
    result = (“not so many”,”more than a dozen”)[eggs>12]
    print result

    a little weird, but cleaner. i guess it is more natural to write tuples in pythonese…

  4. To drewp:

    “The and/or hack has almost-correct evaluation, but with the flaw that [value when false] gets chosen if [value when true] happens to be itself false.”

    If I understand your comment, it is inexact:
    [False] is True because it is a non-empty sequence

    (True and [False] or [22])[0]
    Out[1]: False

    This solution, albeit unreadable, is better than the other solutions because the [value when true] and [value when false]
    are only evaluated if the condition applies.

    In [5]: def p(x):
    print x
    return x
    …:

    In [8]: (True and [p(10)] or [p(22)])[0]
    10
    Out[8]: 10

    In [9]: [p(22), p(10)][True]
    22
    10
    Out[9]: 10

    Bye,
    Luca

  5. I’m learning python right now.

    The more I see, the more I hate it, compared to Ruby.

    No “?:” … and the Python replacement is “better” ?!?!?

  6. @TJIC

    If we all chose languages based on the semantic operators available we’d all be programming in APL right now.

  7. @TJIC
    That’s because you are probably an experienced programmer
    so you know other languages.

    Python is very strict with the rules (forces indentation, etc.)
    but it is (IMHO) very good when it comes to get people started
    into programming, because a beginner will prefer that:

    if (not boxes) and eggs > 12:
    # Start with the pack!
    begin_packing()
    else: print “Not yet.”

    To that:

    if (!boxes && eggs > 12) {
    // Start with the pack!
    beginPacking();
    }
    else System.out.println(“Not yet.”);

    Ruby is also good for beginners, but… 😉

  8. This cuts my indents, sorry.
    Also, I don’t use Python now, but still recommend it for new people.

Leave a Reply

Your email address will not be published. Required fields are marked *