[Tutor] Re: Operators

Magnus Lyckå magnus@thinkware.se
Sat May 3 20:37:02 2003


At 23:02 2003-05-03 +0200, Charlie Clark wrote:
>eek! I've just read the proposal. How do we stop this nonsense? I vote
>against it!

Too late. The vote was a long time ago. It wasn't very
conclusive though.

>You can write
>if x: y(); else: z()
>in one line already and I for one can't see any functional difference
>between this kind of statement and the proposed "ternary operator" and this
>looks like a very special case to me.
>
>But maybe I'm missing something? Can the gurus enlighten me?

The current "if x: y(); else: z()" is a statement. In Python, a
statement is not an expression (which is why we get a blessed
error message if we type "if a=b:" instead of "if a==b:").

The proposed conditional operatator *is* an expression, not
a statement, so you could do something like:

daysOfFebruary = if isLeapYear(year): 29 else: 28

I.e. you want to be able to write

if isLeapYear(year):
     daysOfFebruary = 29
else:
     daysOfFebruary = 28

in a single line.

In C, this is written "daysOfFebruary = isLeapYear(year)?29:28;"

There are certainly situations where you have many conditionals
in the middle of large expressions in C programs, and it would
grow much bigger if you didn't have ?: there.

Today, the typical Python way of doing this is:

daysOfFebruary = isLeapYear(year) and 29 or 28

or more generically

x = c and a or b

The thing is that "A and B" will return "B" if "A" is
true and "A" if A is false:

 >>> print None and 1
None
 >>> print 0 and 1
0
 >>> print 1 and 2
2
 >>> print 1 and None
None

In the case of "c and a or b", b won't even be evaluated
if "c and a" is true. Note that b might be a function call
with side effects.

If "c and a" evaluates to false, "b" will be evaluated, and
its result will be returned. Try it out!

The problem is that this will fail if "a" evaluates as false, e.g.

taxRate = shouldGetReducedTaxes(person) and lowRate or highRate

will allways set taxRate to highRate if the lowRate is 0.

In his particular case, you could do

taxRate = [highRate, lowRate][shouldGetReducedTaxes(person)]

or

taxRate = {1:lowRate, 0:highRate}[shouldGetReducedTaxes(person)]

instead. Using a list or a dict like this is oftem better,
but you can't always to that. Instead of

x = c and a() or b()

you could do

x = [b, a][c]()

but how do you do

x = c and a(p1) or b(p2, p3)

in one line so that a(p1) can return 0 or None, and b will still
not get called if c was true?



--
Magnus Lycka (It's really Lyckå), magnus@thinkware.se
Thinkware AB, Sweden, www.thinkware.se
I code Python ~ The shortest path from thought to working program