question about True values

J

John Salerno

I'm a little confused. Why doesn't s evaluate to True in the first part,
but it does in the second? Is the first statement something different?
print 'hi'


hi
Thanks.
 
P

Paul Rubin

John Salerno said:
I'm a little confused. Why doesn't s evaluate to True in the first
part, but it does in the second? Is the first statement something
different?

No. True and False are boolean values, where booleans are a different
data type from strings, just like strings are different from integers.
print 'hi'

converts s to a boolean during evaluation. That is, it's the same as

if bool(s): print 'hi'

bool(s) is a function that converts s to a bool. If s is a string,
bool(s) is true if s is nonempty, false otherwise.

A comparable thing with integers: suppose

x = 3.1

then "x == 3" is false, but "int(x) == 3" is true.
 
S

skip

John> I'm a little confused. Why doesn't s evaluate to True in the first
John> part, but it does in the second? Is the first statement something
John> different?
... print 'hi'
hi

s is not equal to the boolean object True, but it also doesn't evaluate to
the string class's "nil" value. Each of the builtin types has such an
"empty" or "nil" value:

string ""
list []
tuple ()
dict {}
int 0
float 0.0
complex 0j
set set()

Any other value besides the above will compare as "not false".

Skip
 
M

Mike Kent

John said:
I'm a little confused. Why doesn't s evaluate to True in the first part,
but it does in the second? Is the first statement something different?

print 'hi'


hi

Thanks.

Excellent question! This should help:
False

The value of s is not equal to the value of True. But, the *boolean*
value of s is True, since it is not 0 or an empty string. The python
'if' statement evaluates the boolean value of the condition expression.
 
J

John Coleman

Paul said:
No. True and False are boolean values, where booleans are a different
data type from strings, just like strings are different from integers.

print 'hi'

converts s to a boolean during evaluation. That is, it's the same as

if bool(s): print 'hi'

bool(s) is a function that converts s to a bool. If s is a string,
bool(s) is true if s is nonempty, false otherwise.

A comparable thing with integers: suppose

x = 3.1

then "x == 3" is false, but "int(x) == 3" is true.

But then why is 3.0 == 3 true? They are different types.
 
R

Robert Kern

John said:
I'm a little confused. Why doesn't s evaluate to True in the first part,
but it does in the second? Is the first statement something different?

print 'hi'


hi

They are, indeed, quite different things. Finding the truth value of an object
is not the same thing as testing if the object is equal to the object True. When
people use the phrase "evaluate to True" in the context of an if: statement,
they mean that the truth value of the object (found using the special method
..__nonzero__()) is True, not that it is equal to True.

It's a bit of an abuse on the English language, but what isn't in software?

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

John Salerno

Paul said:
No. True and False are boolean values, where booleans are a different
data type from strings, just like strings are different from integers.

print 'hi'

converts s to a boolean during evaluation.


Oh!!! I get it now! I was thinking that

if s

was the same as

if s == True

because I know sometimes you can write if statements this way (though
it's wordy). But what I didn't realize was that in the cases I was
thinking of, 's' was an expression that evaluated to a boolean value,
not an actual value of some other type!

So I suppose

if (10 > 5)

would be the same as

if (10 > 5) == True

because (10 > 5) does evaluate to "True".
 
P

Paul Rubin

John Coleman said:
But then why is 3.0 == 3 true? They are different types.

The 3 gets converted to float, like when you say

x = 3.1 + 3

the result is 6.1.
 
J

John Salerno

John said:
But then why is 3.0 == 3 true? They are different types.

Good question. Does one type get converted to the other automatically?
That's all I can think of...
 
J

John Salerno

Robert said:
They are, indeed, quite different things. Finding the truth value of an
object is not the same thing as testing if the object is equal to the
object True.

Yeah, I had this in the back of my mind, but I was thinking that this
test would be written as

if s is True

And I know that one is very different from the others.
 
T

Tim Chase

I'm a little confused. Why doesn't s evaluate to True in the first part,
but it does in the second? Is the first statement something different?

print 'hi'

The "if s" does an implicit (yeah, I know, "explicit is better
than implicit") conversion to bool, like

if bool(s):

And as such, you'll find that

bool(s) == True

You can learn more at

http://docs.python.org/lib/truth.html

where you'll see that it's not really exactly a bool() call, but
that strings are a special case listed here. And if not, they
also have a __len__ method which would return zero/non-zero in
the even that strings weren't handled, making the "actual" test
(if strings weren't special-cased)

(s.__len__() <> 0) == True

-tkc
 
J

John Coleman

Paul said:
The 3 gets converted to float, like when you say

x = 3.1 + 3

the result is 6.1.

Yes - it just seems that there isn't a principled reason for implicitly
converting 3 to 3.0 in 3.0 == 3 but not implicitly converting "cat" to
boolean in "cat" == true. There is something to be said about SML's
rigourous approach where 3.0 = 3 isn't even allowed since it is
considered ill-typed. Nevertheless, it is doubtlessly convientent to be
able to compare integers and doubles directly in the natural way and
there is little practical reason to compare a string with a truth value
so Python's solution does have common sense on its side.
 
T

Tim Chase

So I suppose
if (10 > 5)

would be the same as

if (10 > 5) == True

because (10 > 5) does evaluate to "True".

Yes...and similarly,

if ((10 > 5) == True) == True

for the same reason...as does

if (((10 > 5) == True) == True) == True

as does... :*)

-tkc
 
?

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

the string class's "nil" value. Each of the builtin types has such an
"empty" or "nil" value:

string ""
list []
tuple ()
dict {}
int 0
float 0.0
complex 0j
set set()

Any other value besides the above will compare as "not false".

This list of values that are considered false is incomplete,
though. Four obvious omissions are

long 0L
unicode u""
bool False
NoneType None

Not-so-obviously, arbitrary user-defined values can also be
treated as false: If they implement __nonzero__, they are
false if False is returned from __nonzero__; otherwise,
if they implement __len__, they are false if 0 is returned
from __len__. Under these rules, array.array objects can
also be false, as can UserList and UserDict objects.

Regards,
Martin
 
?

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

John said:
Yes - it just seems that there isn't a principled reason for implicitly
converting 3 to 3.0 in 3.0 == 3 but not implicitly converting "cat" to
boolean in "cat" == true.

Sure there is: equality should be transitive. So while we have
3 == 3L == 3.0 == 3.0+0j
and can therefore imply that 3 == 3.0+0j, we should not get
5 == True == ["foo"]
and therefore imply that 5 == ["foo"].

The phenomenon really exists only for numeric types (that two
values of different types still represent the same "thing"),
so it's not surprising that this doesn't readily extend to
other types.

In Python, there are only very few similar cases: byte strings
and unicode strings sometimes compare equal (but, since 2.5,
don't compare unequal very often); lists and tuples could be
considered to have equal values, but don't actually do compare
equal.

Regards,
Martin
 
J

John Coleman

Martin said:
John said:
Yes - it just seems that there isn't a principled reason for implicitly
converting 3 to 3.0 in 3.0 == 3 but not implicitly converting "cat" to
boolean in "cat" == true.

Sure there is: equality should be transitive. So while we have
3 == 3L == 3.0 == 3.0+0j
and can therefore imply that 3 == 3.0+0j, we should not get
5 == True == ["foo"]
and therefore imply that 5 == ["foo"].

The phenomenon really exists only for numeric types (that two
values of different types still represent the same "thing"),
so it's not surprising that this doesn't readily extend to
other types.

In Python, there are only very few similar cases: byte strings
and unicode strings sometimes compare equal (but, since 2.5,
don't compare unequal very often); lists and tuples could be
considered to have equal values, but don't actually do compare
equal.

Regards,
Martin

Very good point, though one could argue perhaps that when one is
comparing an object with a truth value then one is implicitly asking
for the truth value of that object i.e. how it would function if used
in an if statement, etc. This would make code like 'if s: ' equivalent
to 'if s == True:' with a possible gain in readability. But - as you
demonstrate the cost of that (minimal) gain in readability would be too
high. In any event - I think it is mostly bad style to use a
non-boolean variable in 'if s:' - it reminds me too much of obscure C
code (though others might disagree).

-John Coleman
 
G

George Sakkis

Martin said:
the string class's "nil" value. Each of the builtin types has such an
"empty" or "nil" value:

string ""
list []
tuple ()
dict {}
int 0
float 0.0
complex 0j
set set()

Any other value besides the above will compare as "not false".

This list of values that are considered false is incomplete,
though. Four obvious omissions are

long 0L
unicode u""
bool False
NoneType None

Not-so-obviously, arbitrary user-defined values can also be
treated as false: If they implement __nonzero__, they are
false if False is returned from __nonzero__; otherwise,
if they implement __len__, they are false if 0 is returned
from __len__. Under these rules, array.array objects can
also be false, as can UserList and UserDict objects.

A notable exception are numarray arrays (probably true for numpy too, I
haven't tested it though):
from numarray import array
bool(array([1,2]))
Traceback (most recent call last):
File "<stdin>", line 1, in ?
RuntimeError: An array doesn't make sense as a truth value. Use any(a)
or all(a).

George
 
D

Donn Cave

"John Coleman said:
Very good point, though one could argue perhaps that when one is
comparing an object with a truth value then one is implicitly asking
for the truth value of that object

On the contrary -- since there is normally no need to ever
compare an object with a truth value, then I would interpret
this usage as an attempt to distinguish True or False from
other objects in general. Some kind of placeholders for
missing values, who knows. I'm not saying it's a great idea,
but it could work in recent versions of Python.
This would make code like 'if s: ' equivalent
to 'if s == True:' with a possible gain in readability. But - as you
demonstrate the cost of that (minimal) gain in readability would be too
high. In any event - I think it is mostly bad style to use a
non-boolean variable in 'if s:' - it reminds me too much of obscure C
code (though others might disagree).

Others will indeed disagree. I don't think you'll find
much support for this position. But it's not as bad as
your notion that "if s == True", where s is not a boolean
object, might represent a gain in readability. That really
redefines readability.

Donn Cave, (e-mail address removed)
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,162
Latest member
GertrudeMa
Top