Is (-1 ==True) True or False? Neither

Terry Reedy tjreedy at udel.edu
Sat Jan 24 20:08:58 EST 2009


oktaysafak at superonline.com wrote:
> Hi all,
> 
> I ran into a strange case.
> 
> Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit 
> (Intel)] on win32
> ...
>  >>> -1 == True
> False
>  >>> -1 == False
> False
> 
> This works though:
>  >>> if -1:
>     print "OK"
> 
> OK
> 
> After some head scratching, I realized that:
> - bool is a subclass of int and that True and False evaluates to 1 and 
> 0,

Yes, for historical and practical reasons.

> so -1 is equal to neither; and

NO builtin objects other than numbers equal to 1 or 0 are equal to True 
or False.

> - The if -1: statement probably works by treating -1 as bool(-1).

'if condition:' *always* works by calling bool() on the condition, which 
is why one should *never* write 'if bool(exp):'.

> But I can't help finding the former comparison behavior odd.

Every object other than numbers equal to 0 or 1 has the same behavior.

> I admit that it is odd to write such code but when someone writes -1 == True,

It is odd to write such code because the result of comparing two 
constants is or could be known when it is written.  So while one could 
write an optimizer to replace such comparisons with the known value at 
compile time, no one has done so.  (There is an optimizer that sometimes 
replaces arithmetic operations on number constants, but that is because 
writing code that way may make it clearer: for instance, 1<<13 versus 8192.)

> the intention is clearly a boolean comparison, not a numerical value 
> comparison, isn't it?

Nope.  Expecially if either side of the expression in the code is a name 
or collection slot.  As far as the compiler is concerned, '-1' is an 
expression that evaluates to an object and 'True' is another expression 
that evaulates to another object and '==' is a comparison operator which 
it compiles to a call to code that calls the appropriate rich comparison 
methods of either or both of the two objects.

> As far as I understand, to do this comparison, python is casting 
> (loosely speaking) True to its numerical value, rather than casting -1 
> to its boolean value.

I think that this is speaking so loosely as to be misleading.  'Cast' 
has a couple of meaning, neither of which means 'treat a subclass 
instance as a base class instance.'  Subclass instances are 
automatically base class instances and are treated as such by default 
unless there is a subclass method that over-rides the base class method. 
  Bool does *not* over-ride int comparison methods.

 >>> bool.__eq__ is int.__eq__
True

I suspect that the only methods to bool are __new__ (which returns one 
of the only two instances allowed), __str__, and __repr__ (which return 
'False' or 'True' instead of '0' or '1').  Bools are ints, not 'cast to' 
ints.

> So, my question is: wouldn't it make more sense to do just the opposite, 
> i.e. cast -1 to its boolean value and do a boolean comparison of the 
> operands, when one of the operands is True or False?

That would require that ints be subclassed from bool, which does not work.

Terry Jan Reedy




More information about the Python-list mailing list