integer >= 1 == True and integer.0 == False is bad, bad, bad!!!

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Mon Jul 12 20:18:20 EDT 2010


On Mon, 12 Jul 2010 12:34:46 +0200, Jean-Michel Pichavant wrote:

> Well, actually some people might think otherwise. While I disagree with
> the OP flaming style, one could argue that muting an integer into a
> boolean makes no sense (I'm one of them). You can still do it, but there
> is no "right" way to do it.
> You can decide that everything else than 0 is True, but you could also
> pickup the integer 3 as false value, it would work as well since it
> makes no sense. This is just an arbitrary definition. 

Choosing 3 as a false value would be arbitrary, but the choice of 0 is 
anything but arbitrary. The distinction that Python makes is between 
values which are Something (true values) and those which are Nothing 
(false values).

Python has an infinite number of ways of spelling Something:

True, 1, 2, 3.1415, "abc", (2, 4), [None, 1, "A"], ...

and a smaller number of ways of spelling Nothing:

False, None, 0, 0.0, "", (), [], ...

The fact that False == 0 (as opposed to, say, [] != 0) is due to the need 
for backwards compatibility. That bools are implemented as a subclass of 
int is a historical accident. The fundamental distinction in Python is 
between objects which are Something and those that are Nothing, and 
that's not an arbitrary distinction, it's a very deep distinction.

This is why virtually all low-level languages treat 0 as a false flag and 
1 (or sometimes -1) as a true flag. I say "virtually all", not because I 
know of any exceptions, but because in the history of computer languages 
you can probably find every design mistake, arbitrary choice, and 
perverse decision imaginable made by *somebody*.

Consider branch statements. Forth jumps to the "true" branch on any 
integer flag, and to the "false" branch on 0, but the canonical true 
value is either 1 (0000 00001 in binary) or -1 (1111 1111). Early 
versions of BASIC used -1 as true and 0 as false.

With Pascal's strong type-checking, you were forced to use the boolean 
type in branches, but (if I recall correctly) the language guaranteed 
that false was 0 and true was 1: a packed array of bools would use a 0 
bit for false and 1 for true, and an unpacked array would use eight zero 
bits versus seven zeroes and an one.

So there's historical precedent from other languages, backwards 
compatibility with early Python versions, and a fundamental philosophical 
distinction all in favour of using 0 for false. Not arbitrary at all.


> I prefere to explicitly write what I want to test:
> 
> if myInt <> 0:

I would argue against that. Why do you, the coder, care about the 
specific details of treating ints in a boolean context? The int type 
itself knows, leave the decision to it.

Sure, in the specific case of ints, the distinction is so fundamental, so 
basic, and so unlikely to change, that there's no real harm in the 
explicit test. But consider some other type:


if myValue.count <= 0 and myValue.next is None and myValue.blob == "":
    # myValue is considered false

versus:

if not myValue:


Which would you prefer? I think the choice is obvious: the type knows 
whether it is equivalent to true or false, leave it up to the object to 
decide. Why bother making an exception for ints, or strings?



-- 
Steven



More information about the Python-list mailing list