[Tutor] toggle idiom?

Paul Sidorsky paulsid@shaw.ca
Wed, 08 May 2002 23:58:26 -0600


dman wrote:

> The only problem is *if* you want the result to be an integer rather
> than a boolean.  "not a" is a logical operation, not an arithmetic
> one, and the fact that it _happens_ to return 0 or 1 in cpython today
> isn't behavior that should be relied upon.

Actually, it can (unlike in, say, C).  The Python language reference
guarantees it:

> The operator not yields 1 if its argument is false, 0 otherwise.   

Now of course that will change to True and False in 2.3, but like I said
since True == 1 and False == 0 old code won't break.

IIRC in 2.3 int(somevaroftypebool) will return only 0 or 1 as well,
though since bool will be derived from int this conversion is merely
just a declaration of intent.

> | It's been used in C for years, perhaps decades.
> 
> Sure, but in C it is often unclear whether the value is meant as a
> regular number, as a boolean, or as a special case indicator (0 ==
> success , 0 == failure , 0 == NULL , 0 == equality (eg strcmp)).  This
> is my only complaint with the technique -- readability later.  This is
> also why I think adding the built-in names True and False is a Good
> Thing.  (by the same token, no one should write code like
> if expr == True : ...   it should simply be   if expr : ... )

I agree.  Actually I was one of those who were trying to argue in c.l.py
that expr == True should fail iff expr isn't of boolean type so that if
expr was an integer people wouldn't be confused when 5 == True failed,
but unfortunately it would break too much code to use "pure" boolean
variables in this fashion.  Like it or not, many people do rely on the
idioms...

> This requires more conscious thought to understand.  As Kernighan and
> Pike said, use the idiomatic expression of a concept as that is most
> easily recognized by other readers of your code.

Well personally I don't think a C programmer who is reasonably
comfortable with the language would have to think twice about a ? 0 :
1.  But we're talking about Python, not C, so I'll move on.

> | which is really just a short form of what the OP already had, but
> | since Python has no ?: or equivalent this isn't an option.
> 
> a and 1 or 0

This isn't equivalent, though, because it fails if the middle part is
false.  Most people probably know this already, but in case anybody
doesn't:  The "contrapositive" of the above fails because 0 is false:

>>> a = 0
>>> a and 1 or 0           # a ? 1 : 0
0
>>> (not a) and 0 or 1     # !a ? 0 : 1 - should be same as above
1

Furthermore this is an abuse of operators, whereas in C it's a built-in
operation supported by the language.

> *BUT* don't use it!  The reason is the same as above.  It just
> _happens_ that the current implementation of python will return the
> second object rather than normalizing it to a boolean object or some
> such.  In fact, I expect that expression to fail for all future
> versions of python except in the case where 1 and 0 are used (as
> shown)

Yes, unlike the a = not a thing the behaviour of the "psuedo-ternary
operator" is not specified anywhere.  I'm not sure I agree about this
failing in the future, but ideally that's something I'd rather not have
to find out.  :-)

> In summary, I don't really disagree with you (Paul), but there are
> readability (and thus maintainability) repercussions to the various
> styles of operating with values that serve multiple purposes.

Agreed.  Though I'm not sure the following is any better (for integers):

def signum(x):
    if x == 0:
        return 0
    return 1
...
a = signum(a)

This is undoubtedly explicit, but it is really easier to read or
maintain?  One would probably have to look up signum() (or whatever it's
called - the name likely doesn't matter) to find out what it does, and
then a maintenance programmer would have to remember to use this instead
of a = not a to ensure consistent behaviour.

(I realize you were never arguing against using a = not a.  I just
wanted to note that sometimes even the most explicit way isn't ideal.)

BTW the name signum() is something I took from a logic textbook since it
seems appropriate, although in the the text it applies only to natural
numbers.

-- 
======================================================================
Paul Sidorsky                                          Calgary, Canada
paulsid@shaw.ca                        http://members.shaw.ca/paulsid/