question about True values

S

Steve Holden

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

And today's question for the novices is: which Python type did Skip miss
from the above list?

regards
Steve
 
S

Steve Holden

John said:
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).
That's such a well-used (even though sometime abused) Ptyhon idiom that
it's never going to go away.

regards
Steve
 
G

Grant Edwards

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

3 gets promoted to a float. In most (all?) current
implementations, that turns out to be 3.0, but that's not
guaranteed.

It could be argued that promotion of integer types to floats
and shorter integers to longer integers is "a bad thing" in
what's supposed to be a strictly typed language. But, it's one
of those things that done that way because it's always been
done that way.

While it does make life simpler in many cases, it's also a
source of bugs in others.
 
R

Robert Kern

George said:
Martin v. Löwis wrote:
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).

numpy also has this behavior. Numeric yielded to the temptation to guess any(a)
in the face of this ambiguity. Much buggy code was written as a result.

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

Ben Finney

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

And today's question for the novices is: which Python type did Skip
miss from the above list?

bool False
 
T

Terry Reedy

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

And today's question for the novices is: which Python type did Skip miss
from the above list?

more that one:

0L
decimal.Decimal(0) # is decimal.Decimal('0'), also
u''
array.array('c') # or any other typecode, I suspect, without initializer

Terry Jan Reedy
 
G

Gabriel Genellina

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

And today's question for the novices is: which Python type did Skip miss
from the above list?

more that one:

0L
decimal.Decimal(0) # is decimal.Decimal('0'), also
u''
array.array('c') # or any other typecode, I suspect, without initializer

Just for fun:
buffer('')
frozenset()
iter(())
xrange(0)

--
Gabriel Genellina
Softlab SRL

__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam ¡gratis!
¡Abrí tu cuenta ya! - http://correo.yahoo.com.ar
 
S

Steve Holden

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


And today's question for the novices is: which Python type did Skip miss
from the above list?

more that one:

0L
decimal.Decimal(0) # is decimal.Decimal('0'), also
u''
array.array('c') # or any other typecode, I suspect, without initializer


Just for fun:
buffer('')
frozenset()
iter(())
xrange(0)
There's still a very obvious omission ...

regards
Steve
 
C

Carl Banks

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.

Because being true is not the same as equaling True. == is a test for
equaling, not being.


Carl Banks
 
J

John Coleman

Donn said:
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.


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)

As far as readability goes - most computer languages have a surface
syntax which is (by design) vaguely similiar to the syntax of a natural
language like English. Thus statements roughly correspond to sentences.
For example, you can see a subject-verb-object pattern in "x=3". Given
a genuinely boolean construct like x < 2, "if x < 2:" *sounds* right to
a human reader. Similarly, given a good boolean variable with a
descriptive name like "found", the fragment "if found:" sounds ok. But
- given a non-boolean variable like "product_name" - writing "if
product_name:" sounds (to my ears) a little jarring - it sounds like a
sentence fragment. It's like saying "If Bob" - If Bob *what*? Goes to
the store? answers the telephone? Finish the damn thought! Now, if you
were to (from some strange reason) use "product_name" as if it were a
truth value then (to my ears) it would both make your intentions more
clear and sound less fragmentary if you could say "if product_name ==
True:". When you use "product_name" as the condition of an if statement
then in that context it is *functioning* as a truth value so (naively)
what could be wrong with comparing it to a truth value? I don't
advocate any change in Python here - just pointing out that the idea of
allowing "if s:" and "if s == True:" to be always equivalent in the
interest of readability isn't *that* strange. It doesn't constitute a
redefinition of readability.

As far as using non-booleans as conditions - I just think that if you
want a certain block of code to be executed only if, for example, a
list is non-empty, why not *say* so? I think "if my_list != []:" just
reads better than "if my_list:". I would think that my preferences
there mesh with "Explicit is better than implicit" but apparently not.

I'm just starting out with Python with most of my programming in recent
years being in various dialects of Visual Basic (which probably
explains a lot). What attracts me to Python so far is the cool slice
operations, the iterators, the libraries and the convience of
programming in a REPL environment. So far, the ability to use "cat" as
a part-time substitute for True just strikes me as a curiousity - but
maybe that will change with time.

-John Coleman
 
S

Steve Holden

John said:
As far as readability goes - most computer languages have a surface
syntax which is (by design) vaguely similiar to the syntax of a natural
language like English. Thus statements roughly correspond to sentences.
For example, you can see a subject-verb-object pattern in "x=3". Given
a genuinely boolean construct like x < 2, "if x < 2:" *sounds* right to
a human reader. Similarly, given a good boolean variable with a
descriptive name like "found", the fragment "if found:" sounds ok. But
- given a non-boolean variable like "product_name" - writing "if
product_name:" sounds (to my ears) a little jarring - it sounds like a
sentence fragment. It's like saying "If Bob" - If Bob *what*? Goes to
the store? answers the telephone? Finish the damn thought! Now, if you
were to (from some strange reason) use "product_name" as if it were a
truth value then (to my ears) it would both make your intentions more
clear and sound less fragmentary if you could say "if product_name ==
True:". When you use "product_name" as the condition of an if statement
then in that context it is *functioning* as a truth value so (naively)
what could be wrong with comparing it to a truth value? I don't
advocate any change in Python here - just pointing out that the idea of
allowing "if s:" and "if s == True:" to be always equivalent in the
interest of readability isn't *that* strange. It doesn't constitute a
redefinition of readability.
Yes, but you're talking about *your* ears there. I was pointing out, as
others have, that "if product_name" is such a deeply-ingrained Python
idiom that you can use how natural it "sounds" to you as a measure of
your progress in the language.
As far as using non-booleans as conditions - I just think that if you
want a certain block of code to be executed only if, for example, a
list is non-empty, why not *say* so? I think "if my_list != []:" just
reads better than "if my_list:". I would think that my preferences
there mesh with "Explicit is better than implicit" but apparently not.
Maybe so, but that "rule" (and let's not forget that the zen is not
actually a set of prescriptive rules but rather guidelines for the
informed) is immediately preceded by the most important "rule" of all:
"Beautiful is better than ugly". Nobody will shout at you (well,
hopefully, not on this list they won't) for writing

if my_list != []:
...

in your code, but if they have to incorporate it into their own they
will almost certainly reduce it to

if my_list:
....

It's just idiomatic in Python, the same way that "'Sup?" is idiomatic in
English (or what passes for it nowadays ;-) but grates on those who
aren't used to hearing it.
I'm just starting out with Python with most of my programming in recent
years being in various dialects of Visual Basic (which probably
explains a lot). What attracts me to Python so far is the cool slice
operations, the iterators, the libraries and the convience of
programming in a REPL environment. So far, the ability to use "cat" as
a part-time substitute for True just strikes me as a curiousity - but
maybe that will change with time.
It probably will, but I wouldn't get too hung up on what's definitely a
small point. Enjoy Python the way it is, and the way you are. You and
Python will definitely come to an accommodation (and you will love the
combination of discipline and freedom that it brings to programming
style). Welcome to the language!

regards
Steve
 
S

skip

Skip> string ""
Skip> list []
Skip> tuple ()
Skip> dict {}
Skip> int 0
Skip> float 0.0
Skip> complex 0j
Skip> set set()
Skip>
Skip> Any other value besides the above will compare as "not false".

Ben> bool False

In my rush to reply I missed several others as well. Elucidation left as an
exercise for the reader.

Skip
 
S

Steven D'Aprano

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

if s

was the same as

if s == True

No. But you know that now :)
because I know sometimes you can write if statements this way (though
it's wordy).

You can, but shouldn't.

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)

Is the same as:

if True

because (10 > 5) evaluates as True.

would be the same as

if (10 > 5) == True

Did you mean

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

or

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

or even

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

I hope you see my point now.

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

I think it is a good time to remind people of some extremely well-thought
out opposition to the introduction of bools to Python from Laura Creighton:

http://mail.python.org/pipermail/python-list/2002-April/095878.html

She lost the debate, Guido had the final word and Python now has bools.
Take particular note of her description of Python distinguishing between
Something ("cat", 4, [0, 1, 2] etc) and Nothing ("", 0, [] etc).
 
D

Donn Cave

Steve Holden said:
Maybe so, but that "rule" (and let's not forget that the zen is not
actually a set of prescriptive rules but rather guidelines for the
informed) is immediately preceded by the most important "rule" of all:
"Beautiful is better than ugly". Nobody will shout at you (well,
hopefully, not on this list they won't) for writing

if my_list != []:
...

in your code, but if they have to incorporate it into their own they
will almost certainly reduce it to

if my_list:
....

It's just idiomatic in Python, the same way that "'Sup?" is idiomatic in
English (or what passes for it nowadays ;-) but grates on those who
aren't used to hearing it.

It is idiomatic, but not _just_ idiomatic. The former requires
a list object (or a tricky __eq__()), the latter works with a variety
of objects, exhibiting a useful polymorphism.

As for similarities between computer programming languages
and natural languages, I think that breaks down pretty fast.

Part of the problem is something that pinches Python pretty
hard right here, a lack of words that conveniently express
important concepts in the language. A few posts back, Carl
Banks made a distinction between "equaling" and "being", and
if I understood that right, it expresses a fundamental notion
about the meaning of Python's "if", "while" etc. statements.
Unfortunately, though, English conflates existence and identity
in this word ("be"), so it's not going to serve our purposes
very well, and when it comes to words like "if" -- well, we
just have to use what we have.

If there were better words to use with the notion of
"something-ness", I think we would see booleans as a silly
thing of little use to Python programmers. If you can see
"if" and "while" as constructs that respond to something-ness,
you will appreciate idiomatic Python better, because that
arguably is just what it's about.

Donn Cave, (e-mail address removed)
 
F

Fulvio

***********************
Your mail has been scanned by InterScan MSS.
***********************


 >>> s = 'hello'
 >>> s == True
False
 >>> if s:
        print 'hi'
this isn't only a python behavior.
the  "if" test is valid for all non-zero variables. only None, 0 and False
make the condition to jump over.

F
 
G

Gabriel Genellina

I get that iter(()) is True (Python 2.3.4).

It's False on 2.4.2 - and perhaps it's what one would expect, but
since this behavior is not documented anywhere, one should not count on it.


--
Gabriel Genellina
Softlab SRL

__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam ¡gratis!
¡Abrí tu cuenta ya! - http://correo.yahoo.com.ar
 

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,792
Messages
2,569,639
Members
45,351
Latest member
RoxiePulli

Latest Threads

Top