# conditional expressions

Bengt Richter bokr at oz.net
Fri Sep 27 18:22:22 CEST 2002

On Fri, 27 Sep 2002 07:23:53 GMT, Alex Martelli <aleax at aleax.it> wrote:
[...]
>Terry Reedy wrote:
>
>>
>> "Alex Martelli" <aleax at aleax.it> wrote in message
>> news:7nHk9.172208\$pX1.6117207 at news2.tin.it...
>>> The reason
>>>         zz = a and b or c
>>> is not the same thing as
>>>         zz = a ? b : c
>>> is that, when a is true and b is false, the former returns c,
>>> while the latter returns b.
>>
>> In almost all the practical cases where I have thought about using
>> this,  b is *not* false or cannot become false, in which important and
>> real case the two expressions *are* equivalent.
>
>A typical, frequent, practical case is classification, e.g.:
>
>"Append bleep to list truebleeps when bleep is true, append it
>to list falsebleeps instead when false".
>
>If we had a ternary operator, a natural way of expression would be:
>
>    (bleep?truebleeps:falsebleeps).append(bleep)
>
>Of course this would be a disaster with the and/or idiom instead:
>
>    (bleep and truebleeps or falsebleeps).append(bleep)
>
>As list truebleeps starts out empty, thus false, this buggy code
>would NEVER append anything to it.
>
>In this case, like in most others (but far from all!) we don't
>need short-circuiting, so we can perfectly well code:
>
>    (truebleeps, falsebleeps)[not bleep].append(bleep)
>
>This is now correct -- but still nowhere as clear as good old:
It's correct given that truebleeps and falsebleeps are simple references
with no possible side effects from use as above, but I think it's
important to note that the side effect restriction makes it
not semantically identical to
>
>    if bleep: truebleeps.append(bleep)
>    else: falsebleeps.append(bleep)
>
when there is more to it than simple references.
>which to me remains the canonical way to code this in Python.
>Yes, it IS fractionally more verbose, but, so what?  It's
>immediately obvious, simple, and not clever.
>
E.g., if truebleeps and falsebleeps were properties,

if bleep: objectHavingProperty.truebleeps.append(bleep)
else: objectHavingProperty.falsebleeps.append(bleep)

would not trigger potential side effects of respective property getter functions, whereas

(objectHavingProperties.truebleeps,
objectHavingProperties.falsebleeps)[not bleep].append(bleep)

would. I think it worth repeating that short-circuiting was (ISTM) invented to
allow expressions where the terms preceding others in left-right order
**prevent evaluation** of succeeding terms as soon as they cannot affect the total
boolean value, so we can e.g. avoid exceptions in writing things like

if i>0 and i<len(aList) and aList[i] is not None: foo(aList[i])
>
The ternary expression also has the feature of preventing evaluation of the
non-selected term. Someone else brought this aspect up before, but I think
it's important enough to repeat.

>> I think this is an elegant hack, and so I shared it in response to the
>> OP.  Others think it ugly.  So be it.
>
>It's _dangerous_ -- to use it, one always has to be fully aware
>of the risk that subexpression b might be false.  I think this
>is a pitfall just waiting for the unwary to stumble.  Not being
>an aesthete, I consider that more important than issues of beauty.
>
I'd like pitfall-free beauty ;-)

Regards,
Bengt Richter