"0 in [True,False]" returns True

Chris Mellon arkanes at gmail.com
Tue Dec 13 09:08:45 EST 2005


On 13 Dec 2005 11:29:10 GMT, Antoon Pardon <apardon at forel.vub.ac.be> wrote:
> Op 2005-12-13, Steve Holden schreef <steve at holdenweb.com>:
> > Antoon Pardon wrote:
> >> Op 2005-12-13, Steve Holden schreef <steve at holdenweb.com>:
> >>
> >>>Pierre Quentel wrote:
> >>>
> >>>>Hi all,
> >>>>
> >>>>In some program I was testing if a variable was a boolean, with this
> >>>>test : if v in [True,False]
> >>>>
> >>>>My script didn't work in some cases and I eventually found that for v =
> >>>>0 the test returned True
> >>>>
> >>>>So I changed my test for the obvious "if type(v) is bool", but I still
> >>>>find it confusing that "0 in [True,False]" returns True
> >>>>
> >>>>By the way, I searched in the documentation what "obj in list" meant and
> >>>>couldn't find a precise definition (does it test for equality or
> >>>>identity with one of the values in list ? equality, it seems) ; did I
> >>>>miss something ?
> >>>>
> >>>
> >>>It actually uses the __contains__() method of the right-hand operand,
> >>>and in the case of a list that will test for equality of the left-hand
> >>>operand to one of the list elements. Since False == 0 that's why you see
> >>>what you do.
> >>>
> >>>The really interesting question your post raises, though, is "Why do you
> >>>feel it's necessary to test to see whether a variable is a Boolean?".
> >>
> >>
> >> I can give you one example. I have written a tube class. A tube behaves
> >> like Queue but it has additional code so that it can be registed with
> >> gtk in the same way as file descriptor can be registered with
> >> io_add_watch. The way this is implemented is by registering an idle
> >> handler when the tube is not empty and removing it when the tube is
> >> empty. So I have a variable cb_src (for callback source) that can be
> >> a boolean or an integer. The possible values are
> >>
> >>   False: Not registered by the user
> >>   True: Registered by the user but no nternal idle callback registerd
> >>   a number: gtk integer ID, from the registered idle callback handler.
> >>
> > Well I guess you'd better hope that gtk never returns a zero or one, then.
>
> Why? It won't break my code.
>
> > Note, though, that True and False are defined to be singleton instances,
> > so it *is* permissible to say
> >
> >      if i is False:
> >
> > >>> 0 is False
> > False
> > >>> 1 is True
> > False
> > >>>
> >
> > However I must say the coupling in that interface has a very definite
> > code smell. Why not use two variables, a Boolean "registered" and an
> > integer ID that is meaningless when registered is False?
>
> Because the integer ID can be meaningless when registered is True.
> If I should use two variables, the "registered" variable should
> be a three value variable. Something like:
>
>   0: Not registered by the user
>   1: Registered by the user but no internal idle callback registerd
>   2: internal idle callback registerd
>
> Only in the last case is the integer ID meaningfull. But IMO I buy
> nothing buy seperating the information over two variables. Checking
> whether the "registered" variable is 2 or not, doesn't buy me
> anything over checking whether the cb_src is of BooleanType or
> not.
>
> And having the information in one variable means I have to worry
> less about synchronisation. If I register the internal idle
> handler I just store its ID in cb_src, without having to worry
> about another variable that has to be set right.
>

This is the sort of horrible smelly wretchedness that makes me gag in
C. Bearing in mind that you of course are free to write your code in
whatever way you want, and I'm not your boss, this is horrible and
shouldn't be considered something to be catered for.

First and most importantly, you're replacing a literate,
self-documenting mechanism with an obtuse one.

if self.userRegisteredCallback:

is much, much better than

if type(self.callback) is bool:


If you have a consistent API and you're checking for error values from
your GTK functions, then you already have a lot more code than using 2
varaibles will cost you. 10 lines, maybe.

The fact that you think setting two variables is "too hard" but you're
perfectly happy with checking for boolean types instead just testing
truth values I think is a real problem. You aren't saving yourself any
performance. You're barely even saving yourself any typing, and you're
making your code (intentionally, it seems) that much more compllicated
and hard to understand.

Granted, of course, it's your code. But I wouldn't accept it in
anything I was in charge of.


> --
> Antoon Pardon
> --
> http://mail.python.org/mailman/listinfo/python-list
>



More information about the Python-list mailing list