Is (-1 ==True) True or False? Neither
tjreedy at udel.edu
Sun Jan 25 02:08:58 CET 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
> >>> -1 == False
> This works though:
> >>> if -1:
> print "OK"
> After some head scratching, I realized that:
> - bool is a subclass of int and that True and False evaluates to 1 and
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
> - 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__
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'
> 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