tags:

views:

396

answers:

6

I just found this :

a = (None,)
print (a is True)
print (a is False)
print (a == True)
print (a == False)
print (a == None)
print (a is None)
if a : print "hello"
if not a : print "goodbye"

which produces :

False
False
False
False
False
False
hello

So a neither is, nor equals True nor False, but acts as True in an if statement.

Why?

Update :

actually, I've just realized that this isn't as obscure as I thought. I get the same result for a=2, as well (though not for a=0 or a=1, which are considered equal to False and True respectively)

A: 

(None,) is a tuple that contains an element, it's not empty and therefore does not evaluate to False in that context.

meder
... but the question relates to the "boolean" view of the logic operation...
jldupont
+1  A: 

Because a=(None,) is a tuple containing a single element None

Try again with a=None and you will see there is a different result.

Also try a=() which is the empty tuple. This has a truth value of false

gnibbler
+1 to counter whoever downvoted, at least we attempted to explain and that deserves some credit. :)
meder
+4  A: 

a is a one-member tuple, which evaluates to True. is test identity of the object, therefore, you get False in all those test. == test equality of the objects, therefore, you get False again.

in if statement a __bool__ (or __nonzero__) used to evaluate the object, for a non-empty tuple it should return True, therefore you get True. hope that answers your question.

edit: the reason True and False are equal to 1 and 0 respectively is because bool type implemented as a subclass of int type.

SilentGhost
Actually, there's a clearer statement on the 1, 0 thing in http://docs.python.org/library/stdtypes.html#truth-value-testing. It's a matter of definition of the `bool` function, not a coincidence of implementation.
S.Lott
@S.Lott: hm, http://docs.python.org/3.1/reference/datamodel.html#object.__bool__ says that `__bool__` can only return boolean values.
SilentGhost
why the downvote?
SilentGhost
A: 

In Python every type can be converted to bool by using the bool() function or the __nonzero__ method.

Examples:

  • Sequences (lists, strings, ...) are converted to False when they are empty.
  • Integers are converted to False when they are equal to 0.
  • You can define this behavior in your own classes by overriding __nonzero__().

[Edit]

In your code, the tuple (None,) is converted using bool() in the if statements. Since it's non-empty, it evaluates to True.

Bastien Léonard
+1 to counter whoever downvoted, at least we attempted to explain and that deserves some credit. :)
meder
+5  A: 

I find almost all the explanations here unhelpful, so here is another try:

The confusion here is based on that testing with "is", "==" and "if" are three different things.

  • "is" tests identity, that is, if it's the same object. That is obviously not true in this case.
  • "==" tests value equality, and obviously the only built in objects with the values of True and False are the object True and False (with the exception of the numbers 0 and 1, of any numeric type).

And here comes the important part:

  • 'if' tests on boolean values. That means that whatever expression you give it, it will be converted to either True or False. You can make the same with bool(). And bool((None,)) will return True. The things that will evaluate to False is listed in the docs (linked to by others here)

Now maybe this is only more clear in my head, but at least I tried. :)

Lennart Regebro
+1  A: 

Things in python don't have to be one of True or False.

When they're used as a text expression for if/while loops, they're converted to booleans. You can't use is or == to test what they evaluate to. You use bool( thing )

>>> a = (None,)
>>> bool(a)
True

Also note:

>>> 10 == True
False
>>> 10 is True
False
>>> bool(10)
True
hasen j