Alternative suggestion for conditional expressions (see PEP 308)

Mark 'Kamikaze' Hughes kamikaze at kuoi.asui.uidaho.edu
Fri Jul 16 13:10:11 EDT 2004


Colin J. Williams <cjw at sympatico.ca>
wrote on Fri, 16 Jul 2004 09:49:22 -0400:
> I was inclined to support PEP 308, but now wonder whether it's really 
> needed.
> sColorName = ("Black","White")[Color == COLOR_WHITE]
> Could be:
> sColorName = Color == COLOR_WHITE and "Black" or "White"
> which takes avantantage of the short circuit evaluation
> sColorName= color == colorwhite and "white" or garbage
> This gives the correct result when only the first case needs to be 
> evalutated.

  This works only as long as the results of the (true, false) choices
both evaluate true:

>>> def foo():
...     print "eval foo"
...     return "foo"
...
>>> def bar():
...     print "eval bar"
...     return "bar"
...
>>> False and foo() or bar()
eval bar
'bar'
>>> True and foo() or bar()
eval foo
'foo'

  Looks good, right?

>>> def foo():
...     print "eval foo"
...     return ""
...
>>> False and foo() or bar()
eval bar
'bar'
>>> True and foo() or bar()
eval foo
eval bar
'bar'

  Alas.  Not only does it evaluate both, causing who-knows-what side
effects, it returns the wrong answer.  Your Python nuclear missile
launch program goes out of control.  All die.  O the embarassment.

  This is why we do actually need a ternary.  It's not that the language
lacks tools for choosing now, but that this behavior is so very easy to
get wrong, and leads to very subtle bugs.

  The PEP 308 vote showed that at least 84% of the Python users wanted a
ternary.  A second vote between the four major choices would have
obviously ended us up with the (if <cond1>: <expr1> elif <cond2>:
<expr2> ...  else: <exprN>) form, which is about as Pythonically
unambiguous as you can get.

  At the time, my opinion was that I didn't need a ternary often enough
to care.  Sometimes I want to modify some math depending on a boolean,
and in that case I can just treat it as 0 or 1:

>>> 5 + 3 * True
8

  And the rest of the time, it's easy (if tedious) to just write:

>>> if True: a=foo()
... else: a=bar()
...
eval foo
>>> a
''

  However, the ease of doing the and...or and ()[] versions wrong, and
how unbelievably ugly the latter is, have changed my mind from "this is
not important" to "this is something Python really does need, after
all".

-- 
 <a href="http://kuoi.asui.uidaho.edu/~kamikaze/"> Mark Hughes </a>
"The void breathed hard on my heart, turning its illusions to ice, shattering
 them.  Was reborn, then, free to scrawl own design on this morally blank
 world.  Was Rorschach." --Alan Moore, _Watchmen #6_, "The Abyss Gazes Also"



More information about the Python-list mailing list