I’m annoyed with Python’s ternary operator

The ternary operator is a way to concisely say:
“If test, then a, else b“,
with the value of the statement being the value of a or b.

language how to say it
C test ? a : b
C++ test ? a : b
javaScript test ? a : b
Perl (not perl 6) test ? a : b
PHP test ? a : b
Ruby test ? a : b
Did I forget some language? probably
Python a if test else b


Ok. Now that I’ve written this post, I’ll remember it.

However, I just want to say…
On behalf of all of the other multiple-language programmers in the world, …

Update: No really, why??
Well, there are some reasonable reasons.
As noted in the comments, the Python version is more readable (at least in English).
And, to tell you the truth, if I ONLY were programming in Python, I’d probably prefer the Python version.
However, I don’t. I spend quite a bit of time in C++, Perl, PHP, and javaScript. And they ALL use the other form!

I understand the reasoning behind Python’s version.

Rant over

Glad I’ve gotten that off my chest.


  1. Yup says

    Wouldn’t be the first time Python did something a little differently than the other popular languages. What’s this thing about whitespace? Having said that, it rolls off the tongue a little easier if you’re a native english speaker:

    Where are you going today?

    The beach if the weather is nice else I’ll just stay home.

  2. says

    Don’t use “test and a or b”, in some situations it doesn’t do what you think it does. Better would be to use “(test and [a] or [b])[0]”, but look at how hideous it is :)

    The ternary operator was put in exactly to help avoid ugly, low level code like this. Sure it’s different than other languages, but it’s not like you’ll have to look it up constantly. I remembered it the first time I saw it, which to me is a hallmark of good design, just like f.e. comprehensions.

  3. says

    My biggest nit with python’s ternary operator is that it is rather long when you’re trying to keep lines short (ie pep8 compliant). I’m a fan of short lines, but saving a few characters would be handy when you have some longer attribute / variable names.

  4. says

    All those languages essentially copied it from the granddaddy (i.e., C). Also, the ternary operator (properly called “conditional expressions”) are a relatively recent addition to Python (2.5) and from what I heard Guido resisted adding it. And the BDFL also didn’t copy other C features, e.g., increment/decrement operators, || and && for Boolean operations, switch/case statements, and not least: BRACES!!! (for scope, of course).

  5. says

    To be fair, I find the inconsistency to be a little jarring too. While a lot of python flows nicely this jars; and working across multiple languages is one of those oddities you need to remember for apparently no good reason.

  6. says

    The thing I like about Python (over, say, C++, as an example), is that the “small code” like this is more expressive – to my eye, anyway.

    “a if test else b” is closer to english than “test ? a : b”, and that can only be a good thing. Yes, it’s different to most other languages, but then, Python is better than most other languages as well!

  7. Simon Hibbs says

    Sorry but no, the ternary operator is a way to say something, not necessarily a way to concisely say it. You’re loading the argument by implying that terseness, as a desirable feature, has some special status over any others such as readability.

    Python’s syntax is informed by the insight that code is read a lot more often than it’s written, and there’s no guarantee that the reader happens to be familiar with any other programming language.

  8. says

    I know I am picking at straws but what about SQL? WHEN something THEN x ELSE y END

    I agree with people saying it rolls off the tongue better. I also program in multiple languages but this is something I can, quite happily, live with.

    • miyuki says

      This expression has different semantics: both expressions, b and c are evaluated. If ternary operator is used, only one of b or c (depending on value of a) gets evaluated.

    • TutNichtsZurSache says

      The problem isn’t operator precedence but associativity. I. e.
      a ? b : c ? d : e isn’t a ? b : (c ? d : e) but (a ? b : c) ? d : e.

  9. Bryan says

    CoffeeScript also has a screwed-up ternary “operator”. foo = if x > y then “cake” else “pie”
    SO much more typing than JavaScript or most other languages…

  10. Don X says

    Almost every time I hear people use “if” in English, it is always before anything else. If x then y else z comes from that, x ? y : z is just a natural short way of saying the same thing.

    “If it is not raining today, I go outside.”
    “I go outside, if it is not raining today.”

    Which one is easier to understand? I see the first used much more often than the second, and the second makes it hard to see that it is a conditional until after you already hear/read everything else, so it is more confusing. Especially if the statement is very long.

  11. miyuki says

    >Did I forget some language? – probably
    In lua there is an interesting idiom for ternary operator. Logical operators are “short-circuited” (this means that the expression “true and x” will return the value of x, even if x is not boolean), that’s why ternary operator looks like this:
    “test and a or b”

  12. eplimish says

    I wouldn’t say CoffeeScript is screwed – it’s just the consequence of allowing the if-the-else construct as an expression. Scala also allows this as does Ruby (although Ruby also has the test ? true_v : false_v expression – but then Ruby also evaluates everything as true except nil and false – including 0, 0.0 and empty collections – you want uniformity?).

    Given the lack of new semantics, it is obvious to a newbie programmer what is going on, although it does allow the possibility of nightmarish nested if-then-(if-then-else)-else-(if-then-else) tangles. I have had in the past a programmer come to me and say “I haven’t a clue what is meant by this!!” when confronted with the C style ternary op – but that was before widespread availability of the Internet. And certain managers I have know went apoplectic at the use of the C ternary op to the point of banning it in coding standards completely – but generally because it could be abused the same way as if-then-else as an expression.

    I guess BDFL did not want to introduce new terms into the language syntax – if and else were already there, while at the same time avoiding the pitfalls of test and not_always_true_value or default_value. Also you would have to be crazy to abuse the syntax, which although awkward, kind of suppresses the following abuses even in the most operator-obsessive programmer.

    from itertools import combinations_with_replacement as cwr
    def foo(a, b, c):
    return (1 if b else 2) if a else (3 if c else 4) # ugh

    for t in cwr((False, True), 3):
    print “foo{} :-> {}”.format(t, foo(*t))

    It works! But it does introduce a certain amount of self policing. But you would see it a lot more if BDFL had allowed:

    #### won’t work
    def foo(a, b, c):
    return a? (b? 1: 2) : (c? 3: 4) # I knew quite a few people who liked to do this

    or even

    #### won’t work either
    def foo(a, b, c):
    return if a: (if b: 1 else: 2) else: (if c: 3 else: 4) # probably wrecks the parser!!!

    And that’s what he was on about with a language that insisted on indentation in the first place I imagine.

  13. Riku says

    Python’s ternary if may be a little bit annoying and verbose, but unlike the commonly used ?: operator, Python’s ternary conditional expression is composable, so you may have more than one condition like this:

    ‘FizzBuzz’ if x%5==0 and x%3==0
    else ‘Fizz’ if x%3==0
    else ‘Buzz’ if x%5==0
    else str(x)
    for x in range(1, 101)))

    Doing the same with C-style ?: operator will be very hard to read.

    • MrG says

      for (int x=1; x<101; x++) {
      string s = (x%5==0 and x%3==0) ? "FizBuzz" :
      (x%3==0) ? "Fizz" :
      (x%5==0) ? "Buzz" :
      cout << s << endl;

      Range/list objects are python's forte, but the actual ternary op code looks a bit easier to read in C++ to me… At worst, it looks no less clear than the python equivalent..

      Trying to be as impartial as possible when looking at this… I love both languages..

  14. says

    Why write four lines of code when you can use a quarter-line idiom that so many languages use. One of the most useful and clear cases of ternary usefulness is to get around the divide by zero scream. That’s just one example, and so common that it is sad news that we ‘should’ write a whole if-statement to deal with it. (As an aside, I find that the invasion of ‘should’ into programming, the appearance of Best Practices that constrains coders to accommodate all future possibilities despite the improbability of those possibilities, has led to a profusion of verbose code and the conversion of coder culture into a righteous priesthood! Flame off.)

    I like Python, my scripting language of choice, and will use it unless some other tool is obviously a better tool for the task, but it does have its clunkers — and the ternary operator is one heavy clunker. As someone who has productively and clearly enough used the ternary in a number of languages, I find the Python representation dreadful.

    It may have something to do with the limits of the interpreter. Perhaps accommodating the classic ternary would require code that would burden the interpreter? That is the only acceptable excuse for this travesty.

    I will live with it. It’s ok. I still like Python and will continue to use its silly ternary.

  15. Jon Rosen says

    For me, this idiom goes way back to the 1970s when it appeared in several languages, including a database language which had a construct using a straight IF-like expression: a = if x > 0 then y else z; The importance of any form of the ternary operator is the recognition that it is actually a function in disguise (as is any operator) whereas the normal IF statement is a flow-of-control device. The downside of an IF statement used to perform a functional operation is that it can easily be written to be incomplete (forgetting the ELSE or being assymetric (IF x > 0 THEN a = y; ELSE b = z; which is very different because you are assigning to two different variables. Ternary operations provide alternative cases within the expression algebra and are extremely important. SQL didn’t have this for years and since it also didn’t have flow of control within its queries (as flow of control was expressly controlled by the query engine) this was a HUGE fail until the CASE expression was added… I have never been particularly bothered by any of the forms (the C syntax OR the python syntax or other syntaxes) as long as it came with appropriate and complete associativity and short-circuiting. As long as the functionality exists, you can do what you need to do in the relevant language. It was a big complaint of mine about Python until 2.5.

  16. Otto Leichliter says

    consider these:
    perl: print (( $i % 3 ) ? ( $i % 5 ) ? “$i\n” : “buzz\n” : ( $i % 5 ) ? “fizz\n” : “fizz buzz\n” );
    python: print ( ( str(i)+”\n” if ( i % 5 ) else “buzz\n” ) if ( i % 3 ) else ( “fizz\n” if ( i % 5 ) else “fizz buzz\n” ))

    python needs extra parenthesis to understand this whereas perl doesn’t and neither do I and that’s not to mention using str(i)+”\n” as opposed to “$i\n”

  17. says

    I’m not really bothered by Python’s trinary operator. It’s verbose, but I find the more concise a? b : c annoying to read at times.
    What I do miss is an Elvis operator, e.g. var = something ?: default
    Or better, the not null getter: var = obj?.attr1?.attr2 is equivalent to var = obj.attr1.attr2 if obj is not None and obj.attr1 is not None else None but much nicer to read.

  18. Neil says

    This irritates me to no end, not so much because it’s different from the C ternary syntax, but because (1) the order of the terms doesn’t match the logical ordering that first we do the test and then we look at one of the outcomes. And (2) it’s nice to be able to compare the two alternatives ‘side by side’ without having to ‘skip over’ something in between.

    Notice that no-one complains about Haskell and Ocaml using “if X then Y else Z”. (To me, even the SQL monstrosity “case when X then Y else Z end” would be preferable to what we have.)

Leave a Reply