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

Robert Kern robert.kern at gmail.com
Sat Jan 24 20:23:01 EST 2009


On 2009-01-24 19:07, Oktay Şafak wrote:
> 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 don't do it. There really aren't many use cases for comparing with a boolean. 
Just call bool() on the object.

>>> 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.

Actually, I sum up booleans quite often.

>> 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).

The two positions are not symmetrical. Your position requires special-casing 
equality testing; Python's position doesn't.

> 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.

Then just do "assert i" or "assert bool(i)" and be done with it. There's no need 
to do any comparisons at all.

>  > 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.

True in ['something', False]

In your semantics, this would evaluate to True because ('something' == True) is 
True.

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
  that is made terrible by our own mad attempt to interpret it as though it had
  an underlying truth."
   -- Umberto Eco




More information about the Python-list mailing list