"0 in [True,False]" returns True

P

Pierre Quentel

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 ?

Regards,
Pierre
 
F

Fredrik Lundh

Pierre said:
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 ?
0

but seriously, unless you're writing an introspection tool, testing for
bool is pretty silly. just use "if v" or "if not v", and leave the rest to
Python.

</F>
 
C

Carsten Haese

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 ?

Where/how did you search? http://docs.python.org/lib/typesseq.html
states unambiguously that "x in s" returns "True if an item of s is
equal to x, else False"

HTH,

Carsten.
 
S

Steven Bethard

Pierre said:
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

This seems like a strange test. What is this code trying to do?

If you're sure you have to do this, I would do either:

if isinstance(v, bool):
...

or

if v is True or v is False:
...

But it really seems like this code is trying to code some other language
in Python...

STeVe
 
D

David Wahler

Pierre said:
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
From the docs: Python Library Reference, section 2.3.10.9:
"Boolean values are the two constant objects False and True. They are
used to represent truth values (although other values can also be
considered false or true). In numeric contexts (for example when used
as the argument to an arithmetic operator), they behave like the
integers 0 and 1, respectively."

I don't blame you for not knowing about this; it is rather unintuitive.

-- David
 
B

bonono

Fredrik said:
Pierre said:
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 ?
issubclass(bool, int) True
isinstance(False, int) True
False == 0 True
int(False)
0

but seriously, unless you're writing an introspection tool, testing for
bool is pretty silly. just use "if v" or "if not v", and leave the rest to
Python.
The OP's code(and his work around) doesn't look like he is testing for
boolean but more like the data type of something. I thought there is
some idiom in python which said something like "don't assume" ?
 
F

Fredrik Lundh

The OP's code(and his work around) doesn't look like he is testing for
boolean

which of course explains why he wrote

In some program I was testing if a variable was a boolean

in the post I replied to...
but more like the data type of something. I thought there is some idiom
in python which said something like "don't assume" ?

"think before you post" ?

</F>
 
B

bonono

Fredrik said:
which of course explains why he wrote

In some program I was testing if a variable was a boolean

in the post I replied to...


"think before you post" ?
Don't know what you mean.

He seems to be testing "boolean type", not whether it is true or false.
 
A

Antoon Pardon

Op 2005-12-12 said:
Pierre said:
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 ?
issubclass(bool, int) True
isinstance(False, int) True
False == 0 True
int(False)
0

but seriously, unless you're writing an introspection tool, testing for
bool is pretty silly. just use "if v" or "if not v", and leave the rest to
Python.

That depends on the circumstances. I have code where a particular
variable can be a boolean or an integer. I don't want that code
to behave the same on 0 and False nor on any other number and
True.
 
B

bonono

Antoon said:
Op 2005-12-12 said:
Pierre said:
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 ?
issubclass(bool, int) True
isinstance(False, int) True
False == 0 True
int(False)
0

but seriously, unless you're writing an introspection tool, testing for
bool is pretty silly. just use "if v" or "if not v", and leave the rest to
Python.

That depends on the circumstances. I have code where a particular
variable can be a boolean or an integer. I don't want that code
to behave the same on 0 and False nor on any other number and
True.
Then your program/implementation/requirement is wrong because it
doesn't fit in the use case of "if v:" or "if not v:", refactor ;-)
 
S

Steve Holden

Pierre said:
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?".

regards
Steve
 
P

Paul Rubin

Steve Holden said:
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?".

What's the point of having Booleans, if you can't tell them from integers?
 
A

Antoon Pardon

Op 2005-12-13 said:
Pierre said:
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.
 
E

Erik Max Francis

Paul said:
What's the point of having Booleans, if you can't tell them from integers?

Because

return True

is clearer than

return 1

if the purpose of the return value is to indicate a Boolean rather than
an arbitrary integer.
 
F

Fredrik Lundh

Erik said:
Because

return True

is clearer than

return 1

if the purpose of the return value is to indicate a Boolean rather than
an arbitrary integer.

the real reason booleans were added was that sillyness like

True = 1 == 1
False = not True

and

return 1 # true

and

class Boolean:

def __init__(self, value = 0):
self.value = operator.truth(value)

def __cmp__(self, other):
if isinstance(other, Boolean):
other = other.value
return cmp(self.value, other)

def __repr__(self):
if self.value:
return "<Boolean True at %x>" % id(self)
else:
return "<Boolean False at %x>" % id(self)

def __int__(self):
return self.value

def __nonzero__(self):
return self.value

True, False = Boolean(1), Boolean(0)

were all too common in the wild.

for the full story, see

http://www.python.org/peps/pep-0285.html

and, to briefly return to the original topic, note that

"This PEP does *not* change the fact that almost all object types
can be used as truth values. For example, when used in an if
statement, an empty list is false and a non-empty one is true;
this does not change and there is no plan to ever change this.

The only thing that changes is the preferred values to represent
truth values when returned or assigned explicitly. Previously,
these preferred truth values were 0 and 1; the PEP changes the
preferred values to False and True, and changes built-in
operations to return these preferred values."

in general, returning True and False is pythonic, explicitly testing for
them is not.

</F>
 
S

Steve Holden

Paul said:
What's the point of having Booleans, if you can't tell them from integers?

Booleans are specifically defined as a subtype of int at the C level.
One might also ask "what's the point of having floats if you can't tell
them from integers":

It just so happens that __contains__() uses an equality test (which it
should) and equality tests perform certain coercions (which they
arguably shouldn't, but in that case I wouldn't be the one doing the
arguing).

"""
The only thing that changes is the preferred values to represent
truth values when returned or assigned explicitly. Previously,
these preferred truth values were 0 and 1; the PEP changes the
preferred values to False and True, and changes built-in
operations to return these preferred values.
"""

PEP 285.

regards
Steve
 
B

bonono

Erik said:
Because

return True

is clearer than

return 1

if the purpose of the return value is to indicate a Boolean rather than
an arbitrary integer.
True, but if that is the only reason, Two built-in value of
True/False(0/1) serves the need which is what is now(well sort of). Why
have seperate types and distinguish them ?
False
 
S

Steve Holden

Antoon said:
Op 2005-12-13 said:
Pierre said:
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.

Note, though, that True and False are defined to be singleton instances,
so it *is* permissible to say

if i is 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?

regards
Steve
 
E

Erik Max Francis

True, but if that is the only reason, Two built-in value of
True/False(0/1) serves the need which is what is now(well sort of). Why
have seperate types and distinguish them ?

Because of this:

x = True
y = 1 # but I mean it to represent true

print x, y

Besides, it's not the only reason, but it's a good one.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,835
Latest member
KetoRushACVBuy

Latest Threads

Top