Warts of Python: Ternary Expressions
The problem with Python's ternary operator is that it breaks up the two contrasting values on two opposite sides of the expression.
To break it up into how I myself work with it, let's look at an example that made me opt for a hack.
form.data["type"] = "business" if request.form.get("business") else "private"
And the hack,
form.data["type"] = ("private", "business")[bool(request.form.get("business"))]
The reason is obvious: the above consolidates the literal data to one side of the expression, making it easier to follow the code. (Apart from the occasional guy who doesn't know about the perverted powers of indexing by boolean values!)
The only time the Python ternary works is with very simple conditions, no strike that -- with very short conditions. Complexity has nothing to do with it.
business = bool(request.form.get("business")) form.data["type"] = "business" if business else "private" ## get = request.form.get form.data["type"] = "business" if get("business") else "private"
So I submit that the BDFL made a mistake. The ternary expression in Python sucks.
Perhaps you need some better examples, as the one you submit strikes me as substantially more complicated. It has three more sets of enclosures, and it requires someone to use a boolean as an index (which is fine, but there's nothing particularly intuitive about it).
I think the Python ternary, while unintuitive if you are expecting it to work like ternaries in other language, is very intuitive if you are just reading it, without any particular expectation of a ternary. At least, I believe it would be intuitive to native English speakers, it might be that the order of things makes less sense in other languages.
Finally, compared to your example, the Python ternary enables things like this:
do_a() if a_time else do_b()
For myself, the ternary expression works very well.
Your hack does not delay evaluation on each branch of the ternary operator. What I mean is ("private", "business") is immediately evaluated. What if the two values were something like: (private(), business()) where some expensive logic was computed. You would have unnecessarily evaluated both sides.
Instead you could do:
but that is truly an eyeseore.
I tend to use and expression like:
form.data["type"] = request.form.get("business") and "business" or "private"
While Python's ternary expression isn't perfect, I wouldn't agree that it sucks. IMO, you should only use the ternary expression with short simple expressions anyway. And this applies to any language. If you're writing too complex logic in a ternary expression, the code will be clearer if you split it into two or more expressions.
if your library can not into form.get(key, default) it is retarded
Another tortured boolean construct: form.data["type"] = get("business") and "business" or "private"
shrug As described in PEP 308, conditional expressions exist to solve a very simple problem: getting people to stop using the error prone and/or hack.
Guido's opinion (and that of many core devs) is that, aside from the very short cases where it reads OK, people shouldn't use it at all and instead write out a full if statement.
Yes it does seem a bit awkward in some ways, I agree. But, it's one thing to criticise something, and another thing to propose something different. It seems BDFL and the Python community went through the collaboration process as usual, as summarised in PEP 308, and this is what we got.
If you were the BDFL, what syntax would you have picked?
The ternary syntax is still present in Python 3. Therefore it is not a wart.
You feel that the second example is easier to read? I guess tastes just differ, but I find the first example, the one with the ternary expression, quite a bit easier to read.
It's shorter than your hack example, and it doesn't require me to backtrack on the line to figure out what the heck is going on.
That said, you clearly don't want something super long in the ternary expression. At that point, I would just switch to a real if/then suite instead of opting to index a tuple by a boolean though.
I find the first expression clear, and the second opaque.
If you prefer the literal values to be next to each other, I'd suggest creative line breaks (though I doubt this comments form will let me express myself clearly):
form.data["type"] = ("business" if request.form.get("business") else
Mmm... and if He do it on purpose?
maybe it's better to write
form.data["type"] = "business"
form.data["type"] = "private"
The ternary operator is meant to be used "with very short conditions", just for one-liners
With all due respect, I must disagree. Readability is central to the design of Python, and the ternary expression was introduced explicitly to prevent hacks like (X && P) || Q, or the binary indexing scheme you used (which doesn't appeal to me, because the false condition is listed first).
And the ternary operator holds up well because of those common use cases where a default value needs to be introduced in the absence of an expected value. I deal with NULLs from databases quite a lot, so the ternary expression, as defined by the BDFL, makes sense.
Complexity does enter into it, in such cases. If an expression is so complex that it would read better with the condition split out as a separate expression (or reformulated as part of an "if" statement), then better that the language encourage such syntax.
Your particular use case, though, where the result is one of two literals, is an understandable weakness. But how common is it in practice? And what's so wrong with the two restatements of the example that you provided?
I don't like Python's ternary expression either, but in this particular case I think the example is bad, because you can just do this to solve that use case:
form.data["type"] = request.form.get("business", "private")
Did I misunderstand the example?