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

Oktay Şafak oktaysafak at superonline.com
Sat Jan 24 20:07:04 EST 2009


Robert Kern wrote:
> On 2009-01-24 17:00, 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, so -1 is equal to neither; and
>> - The if -1: statement probably works by treating -1 as bool(-1).
> 
> Yes.

Good.

> 
>> But I can't help finding the former comparison behavior odd. I admit
>> that it is odd to write such code but when someone writes -1 == True,
>> the intention is clearly a boolean comparison, not a numerical value
>> comparison, isn't it?
> 
> Not to me. The rules of Python state that the object on the left hand 
> side is asked first how to compare the two values. Only if that fails is 
> the object on the right hand side asked how to compare the objects.

OK.

>> 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.
> 
> Not really. No casting goes on at all. 

Of course, I said loosely speaking.

> bool is just one of the types that int.__eq__ knows how to handle 
> because bool is a subclass of int. 
> Vice-versa, bool.__eq__ knows how to handle ints, and it also does a 
> numerical comparison; it never casts to a boolean.

That's what I'm trying to say: it would be more meaningful if int.__eq__ 
did a boolean comparison when the other operand is a boolean. And 
bool.__eq__ should as well do a boolean comparison when the other 
operand is an integer (or even a number). The reason is that when 
someone writes (-1 == True) he is clearly, definitely, absolutely asking 
for a boolean comparison, not a numerical one. As I said before, this is 
weird code; but using the True built-in for checking whether a number's 
value is equal to 1 would be even weirder.

> 
>> 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?
>>
>> Or is this too fancy? What do you think?
> 
> I think that being explicit is better than being implicit. 

Well, I agree that explicit is better than implicit: when one wants to 
use the numerical values of True or False, he should make it explicit 
and use int(True) or int(False), but one is never interested in a 
boolean's numerical value (which is nonsense, IMHO). We never write 
counter += True, for example.

> If you want to cast an object to a boolean, use bool() on it. 

Well, I can tell you in response that if you are interested in a 
boolean's *integer* value, than make it explicit and use int(True). When 
I write

assert i == True

I'm not trying to make sure that i is equal to one, I am trying to make 
sure that it evaluates to True (of course True is redundant here but it 
can make the code more readable). If I was interested in the former 
case, it would be most natural to write assert i == 1 but I'm interested 
in the latter and I think Python's treatment is not quite right here.

 > Making special rules when comparing with booleans makes it harder to
 > treat True and False as first-class objects.

I don't see how fixing this makes harder to treat True and False as 
first-class objects. If doing the right thing takes some special casing 
then be it, but I don't think it's so.

Anyway, thanks for the response.

Oktay



More information about the Python-list mailing list