the PHP ternary operator equivalent on Python
Steven D'Aprano
steve at REMOVETHIScyber.com.au
Sat Nov 19 02:02:21 EST 2005
On Fri, 18 Nov 2005 21:05:50 -0800, bonono at gmail.com wrote:
> Steven D'Aprano wrote:
>> WHY WHY WHY the obsession with one-liners? What is wrong with the good old
>> fashioned way?
>>
>> if cond:
>> x = true_value
>> else:
>> x = false_value
>>
>> It is easy to read, easy to understand, only one of true_value and
>> false_value is evaluated. It isn't a one-liner. Big deal. Anyone would
>> think that newlines cost money or that ever time you used one God killed a
>> kitten.
>>
> How do you put this block into list comprehension or generator
> expression ? Why the obsession of these block style ?
Why do you assume that everything you need for your list comprehension has
to go into a single line? Chances are your list comp already calls
functions, so just create one more for it to use.
py> def describe(cond):
... if cond:
... return "odd"
... else:
... return "even"
...
py> L = [describe(n % 2) for n in range(8)]
py> L
['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']
One major advantage is that this makes it easier to test your function
describe() in isolation, always a good thing.
Another advantage is that the idiom "call a function" is extensible to
more complex problems:
def describe(n):
if n < 0:
return "negative " + describe(-n)
elif n == 0:
return "zero"
elif n % 2:
return "odd"
else:
return "even"
L = [describe(n) for n in range(8)]
if much easier to understand and follow than using ternary expressions:
# obviously untested
L = ["zero" if n == 0 else \
"negative " + ("odd" if n % 2 else "even") if n < 0 else \
"odd" if n % 2 else "even" for n in range(8)]
Yes, I've seen ternary expressions nested three and even four deep.
I find it fascinating to read Guido's reasoning for introducing a ternary
statement. From the PEP here http://www.python.org/peps/pep-0308.html he
links to this comment of his:
[quote]
I think Raymond's example is more properly considered an argument for
adding a conditional expression than for removing the current behavior of
the and/or shortcut operators; had we had a conditional expression, he
wouldn't have tried to use the "x and y or z" syntax that bit him.
[end quote]
Looking back to Raymond's example here:
http://mail.python.org/pipermail/python-dev/2005-September/056510.html
[quote]
I propose that in Py3.0, the "and" and "or" operators be simplified to
always return a Boolean value instead of returning the last evaluated
argument.
1) The construct can be error-prone. When an error occurs it can be
invisible to the person who wrote it. I got bitten in published code
that had survived testing and code review:
def real(self):
'Return a vector with the real part of each input element'
# do not convert integer inputs to floats
return self.map(lambda z: type(z)==types.ComplexType and z.real or z)
The code fails silently when z is (0+4i). It took a good while to trace
down a user reported error (when Matlab results disagreed with my matrix
module results) and determine that the real() method contained an error.
Even when traced down, I found it hard to see the error in the code.
Now that I know what to look for, it has not happened again, but I do
always have to stare hard at any "and/or" group to mentally verify each
case.
[end quote]
Dare I suggest that if Raymond wasn't struggling to force the body of his
function real() to be a one-liner, he wouldn't have tried to use the "x
and y or z" syntax that bit him? Brevity is not always a virtue.
--
Steven.
More information about the Python-list
mailing list