LWN.net Logo

Choosing a ternary operator for Python

C and C++ programmers encounter the ternary operator early in their education. This operator, which in C syntax, looks like:

    <condition> ? <expression1> : <expression2>

evaluates to expression1 if (and only if) the given condition evaluates true; otherwise expression2 is chosen. The ternary operator is a compact representation of a common operation (choosing between two values), and it is a heavily-used feature in languages which provide it.

Python does not provide a ternary operator, much to the chagrin a subset of hackers who are otherwise very happy with the language. As a way of responding to years of requests, Python Benevolent Dictator For Life Guido van Rossum posted a proposal for a Pythonic ternary operator, and asked the community to get back to him with its opinion. To say that the discussion was active would be a substantial understatement; thousands of messages were posted discussing the merits of ternary operators, whether Python should have one, and what form it should take. The result was a revised version of PEP 308.

That proposal included a few possible forms for a Python ternary operator. The primary proposal was for this form:

    (if <cond>: <expr1> else: <expr2>)

This form is easily extended to four or more operands:

    (if <cond>: <expr1> elif <cond2>: <expr2> else: <expr3>)

Unusually for Python, the parentheses would be mandatory. For that reason, and the fact that the syntax looks a lot like the regular if/else control structure, not everybody was happy with this proposal. So a number of alternatives were floated as well. They range from the standard C syntax to variants like:

    <cond> and <expr1> else <expr2>
    <cond> then <expr1> else <expr2>
    <expr1> if <cond> else <expr2>
    cond(<cond>, <expr1>, <expr2>)
    <cond> ?? <expr1> || <expr2>
    <cond> -> <expr1> else <expr2>

If this were Perl, the language hackers would have probably just implemented all the possibilities and been done with it. But Python programmers like to have one accepted way of doing things, so a decision had to be made. A vote was held, and the results are now available.

No alternative won a clear majority of the 518 votes counted. The parenthesized syntax from the proposal got the most votes, but the C syntax was not far behind. The "no change" contingent was rather smaller, but very passionate in its arguments. The end result is that vote coordinator Raymond Hettinger has not chosen to certify a winning proposal as such. Instead. he is passing the results back to the Benevolent Dictator who, after all, has a rather larger vote than anybody else. As of this writing, Guido has not made his decision known.


(Log in to post comments)

No need of new syntax

Posted Mar 13, 2003 10:42 UTC (Thu) by sokol (guest, #4383) [Link]

I am not a Python user but it seems that even in its actual form, Python allows a very similar (and elegant IMHO) syntax:

<cond> and <expr1> or <expr2>
(you may put it in paranthesis if you like)

which works *exactly* in the same manner its C sibling:
<cond> ? <expr1> : <expr2>

So why all this hype ?

It's not completely equivalent

Posted Mar 13, 2003 11:01 UTC (Thu) by rschroev (subscriber, #4164) [Link]

As pointed out in the Python FAQ (http://www.python.org/cgi-bin/faqw.py?query=ternary&querytype=simple&casefold=yes&req=search), there is a problem:

"Is there an equivalent of C's "?:" ternary operator?
Not directly. In many cases you can mimic a?b:c with "a and b or c", but there's a flaw: if b is zero (or empty, or None -- anything that tests false) then c will be selected instead. In many cases you can prove by looking at the code that this can't happen (e.g. because b is a constant or has a type that can never be false), but in general this can be a problem."

There is a workaround though:

"Tim Peters (who wishes it was Steve Majewski) suggested the following solution: (a and [b] or [c])[0]. Because [b] is a singleton list it is never false, so the wrong path is never taken; then applying [0] to the whole thing gets the b or c that you really wanted. Ugly, but it gets you there in the rare cases where it is really inconvenient to rewrite your code using 'if'."

In any case, I think using 'and' and 'or' lowers the readability, because it is not obvious what the intent is. A real ternary operator is a good idea.

Re: It's not completely equivalent

Posted Mar 13, 2003 13:32 UTC (Thu) by sokol (guest, #4383) [Link]

Right. I appologize for suggesting a wrong solution.

No need of new syntax

Posted Mar 13, 2003 18:11 UTC (Thu) by petebull (guest, #7857) [Link]

And the operator is allowed as an lvalue as in:

(a ? b : c) = 5

Awkward Voting

Posted Mar 13, 2003 22:15 UTC (Thu) by gleef (guest, #1004) [Link]

With such an awkward voting scheme, it's no wonder they have no clear winner. To select between so many choices, Condorcet voting becomes almost a necessity. I'm not a python developer, but I would suggest that they may actually get an answer to their question if they rerun the vote as follows:

  1. Add any significant write-in's from the first vote to the list
  2. Add "No Tertiary Operator" to the list of choices
  3. Remove "Write In Vote" from the list, there are enough choices
  4. Have every voter submit a fully ranked ballot. Nothing fancy, just rank all the choices (including "No Tertiary Operator") in order of preference. If there are 18 choices, there should be 18 rankings for each ballot
  5. Process those ballots using the Condorcet rules (or one of the widely accepted variations, which only really differ in the method for resolving "circular ties", a very rare occurance).

The result will be a fair indication of the most preferred choice. This voting scheme is not significantly harder on the voters. As for the counters, it's annoying to count lots of these ballots by hand, but we have computers that make it simple.

For more information on the Condorcet Voting system, see The Election Methods Site. For an example of an organization happily using Condorcet for real life decision making see Debian. The system's not perfect, but it's fair and comes up with a good indicator of a preferred compromise choice from a list of many choices.

Copyright © 2003, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds