473,503 Members | 2,135 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

question about True values

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?
>>s = 'hello'
s == True
False
>>if s:
print 'hi'
hi
>>>
Thanks.
Oct 25 '06
90 3364
On 2006-10-26, Steve Holden <st***@holdenweb.comwrote:
John Coleman wrote:
>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 != []:
...
That depends on what you consider as shouting. My impression is that
if people come here with a problem and post a sample of code to
illustrate. That if that code would contain something like the above
about half of the responses will be about the code not following
python idiom without further providing anything helpfull with the actual
problem. Now you may not consider that as shouting but I guess it
can be just as intimidating.
>>
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!
I'll second that. Python has it warts, but so has any language.
Chances are John will find the warts of python are minor
issues compared with other languages.

--
Antoon Pardon
Oct 27 '06 #51
On 2006-10-27, Fredrik Lundh <fr*****@pythonware.comwrote:
Antoon Pardon wrote:
>The latter will treat None and False the same as [], () and {},
which in most of my code is not what I want.

since you never publish any code,
This is not True. You shouldn't confuse your lack of recollection
with reality.
what you do in your code is not very interesting to anyone.
I doubt I'm the only one who has code that treats None and False
differently from [], () and {}

--
Antoon Pardon
Oct 27 '06 #52
Antoon Pardon wrote:
>since you never publish any code,

This is not True. You shouldn't confuse your lack of recollection
with reality.
pointers, please.

</F>

Oct 27 '06 #53
On 2006-10-27, Fredrik Lundh <fr*****@pythonware.comwrote:
Antoon Pardon wrote:
>>since you never publish any code,

This is not True. You shouldn't confuse your lack of recollection
with reality.

pointers, please.
Sorry, the answer is no. I don't care whether you can locate my code
or not or wish to believe me or not.

--
Antoon Pardon
Oct 27 '06 #54
Antoon Pardon wrote:
On 2006-10-27, Fredrik Lundh <fr*****@pythonware.comwrote:
>>Antoon Pardon wrote:

>>>>since you never publish any code,

This is not True. You shouldn't confuse your lack of recollection
with reality.

pointers, please.


Sorry, the answer is no. I don't care whether you can locate my code
or not or wish to believe me or not.
Google finds 2 hits for "Anton Pardoon open source". You are ceratinly
keeping it well hidden.

Few people have more right to call you on this than the effbot, well
known for his prolific output.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Oct 27 '06 #55
Antoon Pardon wrote:
On 2006-10-27, Fredrik Lundh <fr*****@pythonware.comwrote:
>>Antoon Pardon wrote:

>>>>since you never publish any code,

This is not True. You shouldn't confuse your lack of recollection
with reality.

pointers, please.


Sorry, the answer is no. I don't care whether you can locate my code
or not or wish to believe me or not.
.... though I might have got more hits by spelling your name correctly :)

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Oct 27 '06 #56
On Fri, 27 Oct 2006 09:16:57 +0000, Antoon Pardon wrote:
>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/pyt...il/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).

Yes and IMO that is a less usefull distinction than the distinction
between True and False. When I write code I think in terms of
conditions. In those conditions this has to be treated this way
otherwise it has to be treated an other way. Conditions give
results that are either True or False, not Something or Nothing.
And if you read the thread that Laura Creighton's post is part of, you
will see that she acknowledges that most people think strongly in terms
of binary true/false yes/no states, and that this is often the wrong thing
to do. There are lots of human thought patterns that are unhealthy, and
binary is often one of them.

The world is continuous, and our brains think in binary. No wonder people
have such trouble with concepts like evolution:

- there is a continual chain of individuals such that every offspring of
an reptile is a reptile, and every parent of a mammal is a mammal, and
yet mammals are directly descended from reptiles.

By I digress. This is too easy to get off topic...

I don't think of 10 5 as Something while 5 < 10 would be
Nothing.
Not at all, you got your operators the wrong way around. Five certainly is
less than 10 in every counting system I've ever come across. I think you
meant 5 10 is Nothing.

Certainly purely mathematical relations like GT and LT lend themselves
very well to true two-valued algebra. The thing to remember is that
Python's truth model is not the same as pure Boolean algebra. For
starters, it certainly is not two-valued! It is infinitely-valued. It's
just that many of those values are equivalent *in a Boolean context*.

In Pascal, writing "x := 2; if x then..." would be an error, because x is
not a Boolean. But it is certainly useful to be able to write the
equivalent in Python. The designer of Pascal choose strict Boolean
algebra; the designer of Python choose a more flexible, less strict model.

If you are going to argue for strict Booleans, like in Pascal, then
mathematical relations like GT and LT will be your poster-child.

But if you are going to argue for Python's less strict truth model, then
you'll talk about lots of examples like this:

if somelist:
# work with the list
else:
# nothing to work with
So while the paradigma of the language may be the
distinction of Something vs Nothing the programmer will often
enough think in terms of True and False.
If you read Laura's post, you will see that she is arguing strongly that
thinking about True and False is often -- usually! -- a mistake. I
acknowledge that there are cases where it is either necessary or desirable
to think in terms of True/False, but that is less common than you might
think.

So IMO it would have
been better if python had made the distinction between True and
False and so made the programmer code the Something/Nothing
disctinction explicitly.
I don't understand what you are saying here, unless it is that you
believe that Python should have strict Pascal-style Booleans.
--
Steven.

Oct 27 '06 #57
On Fri, 27 Oct 2006 12:54:35 +0100, Steve Holden wrote:
Antoon Pardon wrote:
>On 2006-10-27, Fredrik Lundh <fr*****@pythonware.comwrote:
>>>Antoon Pardon wrote:
>since you never publish any code,

This is not True. You shouldn't confuse your lack of recollection
with reality.

pointers, please.


Sorry, the answer is no. I don't care whether you can locate my code
or not or wish to believe me or not.
Google finds 2 hits for "Anton Pardoon open source". You are ceratinly
keeping it well hidden.

Few people have more right to call you on this than the effbot, well
known for his prolific output.

This may come as a shock to some of us in the Open Source arena, but the
care-factor of code is not necessarily tied to the number of distinct
pieces of code released to the public by the code's author. Many people,
for example, care a lot about the software running in nuclear reactors,
regardless of whether or not the code's author is a prolific Open Source
developer.

Of course Fredrik has a proven track record, and the quality of his code
is out there for any interested person to see. That means that the wise
person, even if he disagrees with Fredrik, should take what he has to say
seriously. If Fredrik is dismissive of Antoon's use of "if len(list) != 0"
instead of "if list", we should take that opinion very seriously.

But for all we know, Antoon's code might be responsible for keeping
nuclear reactors running, planes in the air, missiles hitting their
targets, or some other really critical application. His lack of visible
code doesn't *necessarily* mean we should dismiss what he has to say -- it
merely means that his track record is unproven to us.

And even if he does nothing but write trivial scripts for his own use,
that fact alone doesn't make his opinion wrong or foolish.

But in this specific instance, I don't see any advantage to explicitly
testing the length of a list. Antoon might think that is sufficiently
polymorphic, but it isn't. He cares whether the object has zero _length_,
but for true polymorphism, he should be caring about whether the object is
_empty_. Not all empty objects have zero length, or even a length at all.
(E.g. binary trees.) That's why Python classes can use a __nonzero__
method, falling back on __len__ only if __nonzero__ is not defined.
--
Steven.

Oct 27 '06 #58
***********************
Your mail has been scanned by InterScan MSS.
***********************
On Thursday 26 October 2006 02:56, John Salerno wrote:
*>>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 andFalse
make the condition to jump over.

F
Oct 27 '06 #59
In article <sl********************@rcpc42.vub.ac.be>,
Antoon Pardon <ap*****@forel.vub.ac.bewrote:
....
I think you are incorrect.
Thanks! I rest my case!
And how do I express that a number has to be greater than
100 into a Nothing vs Something dichotomy? Declare all
greater numbers as Something and the rest as Nothing?
Well, would you declare numbers less than 100 False?

Think about it in more philosophical terms. What is Truth?
The Internet Encyclopedia of Philosophy may be some help
with this - http://www.iep.utm.edu/t/truth.htm

Then when you get tired of that, suppose that "if" and
"while" are asking for "yes" and "no", instead of "true"
and "false", and ask yourself if we have the philosophical
problems with "yes" that we do with "true".

Donn Cave, do**@u.washington.edu
Oct 27 '06 #60
On 2006-10-27, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:
But in this specific instance, I don't see any advantage to explicitly
testing the length of a list. Antoon might think that is sufficiently
polymorphic, but it isn't. He cares whether the object has zero _length_,
but for true polymorphism, he should be caring about whether the object is
_empty_. Not all empty objects have zero length, or even a length at all.
(E.g. binary trees.) That's why Python classes can use a __nonzero__
method, falling back on __len__ only if __nonzero__ is not defined.
Nobody can force you to write a container class that also provides a
__len__ method. But if you don't provide one then IMO it is your class
that deviates from standard practice. Mathematically, sets and
directories have no length either, yet the len function does provide
an answer if you give it a set or directory as an argument. So
it seems that python has generalised the len function to provide
the number of elements in the container.

I have written a Tree class(*). It can be used as a drop in replacement
anywhere where a directory is used, as long as there is a full order
relationship in the key domain. That tree class provides a __len__
method that will anser with the number of items in the tree just
as a directory would and I see nothing wrong with that.

Of course I can't account for all possible ways someone wishes to
write a class, but I don't see what is wrong with counting on
the fact that an empty container has a length of zero.

I can write a container class where the truth value of an object
is independent of whether or not the object is empty and then
the "if obj:" idiom will fail to provide true polymorphism too.

(*) http://www.pardon-sleeuwaegen.be/antoon/avltree.html

--
Antoon Pardon
Oct 27 '06 #61
On 2006-10-27, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:
On Fri, 27 Oct 2006 09:16:57 +0000, Antoon Pardon wrote:
>>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/pyt...il/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).

Yes and IMO that is a less usefull distinction than the distinction
between True and False. When I write code I think in terms of
conditions. In those conditions this has to be treated this way
otherwise it has to be treated an other way. Conditions give
results that are either True or False, not Something or Nothing.

And if you read the thread that Laura Creighton's post is part of, you
will see that she acknowledges that most people think strongly in terms
of binary true/false yes/no states, and that this is often the wrong thing
to do. There are lots of human thought patterns that are unhealthy, and
binary is often one of them.
The Nothing/Something dichotomy is just as binary as the True/False
dichotomy. And in the case of deciding whether you will take the
"then" branch or "else" branch I see nothing unhealthy in checking
whether the condition was true or not.
The world is continuous, and our brains think in binary. No wonder people
have such trouble with concepts like evolution:
The world may be continuous, programming structures are discrete.
You take the "then" branch or not. In the latter case you can
again decide to take the elif branch or not. There is nothing
continuous in that.
- there is a continual chain of individuals such that every offspring of
an reptile is a reptile, and every parent of a mammal is a mammal, and
yet mammals are directly descended from reptiles.

By I digress. This is too easy to get off topic...

>I don't think of 10 5 as Something while 5 < 10 would be
Nothing.

Not at all, you got your operators the wrong way around. Five certainly is
less than 10 in every counting system I've ever come across. I think you
meant 5 10 is Nothing.
Yes that was a type, I meant I don't think of 5 10 as Nothing.
Certainly purely mathematical relations like GT and LT lend themselves
very well to true two-valued algebra. The thing to remember is that
Python's truth model is not the same as pure Boolean algebra. For
starters, it certainly is not two-valued! It is infinitely-valued. It's
just that many of those values are equivalent *in a Boolean context*.
That it is infinitely-valued is a red herring. It is partitioned in
two, so all these infinite values are mapped into two possibilities
because at the end you have to decide a simple yes/no question.
Will I repeat the loop or not. Will I take the "then" branch or
not.
In Pascal, writing "x := 2; if x then..." would be an error, because x is
not a Boolean. But it is certainly useful to be able to write the
equivalent in Python. The designer of Pascal choose strict Boolean
algebra; the designer of Python choose a more flexible, less strict model.

If you are going to argue for strict Booleans, like in Pascal, then
mathematical relations like GT and LT will be your poster-child.

But if you are going to argue for Python's less strict truth model, then
you'll talk about lots of examples like this:

if somelist:
# work with the list
else:
# nothing to work with
In most case I just do:

for el in somelist:

which works for empty lists just as good as non-empty ones. So
why should an empty list be treated differently from an non-empty
one if it is used in a boolean context?
>So while the paradigma of the language may be the
distinction of Something vs Nothing the programmer will often
enough think in terms of True and False.

If you read Laura's post, you will see that she is arguing strongly that
thinking about True and False is often -- usually! -- a mistake.
Yes she argues that? So? I think she is wrong and her argument
lacking.
I
acknowledge that there are cases where it is either necessary or desirable
to think in terms of True/False, but that is less common than you might
think.
Control structures in programming languages do nothing else but decide
things in terms of True/False. You may dress things up but in the
end a statement like:

if obj:

Will evaluate/map into a two valued domain, where one value will lead you
into the "then" branch and the other value will not. And IMO the more
clearer the relationship between the written code and the final result
the better.

--
Antoon Pardon
Oct 27 '06 #62
Steven D'Aprano wrote:
But in this specific instance, I don't see any advantage to explicitly
testing the length of a list. Antoon might think that is sufficiently
polymorphic, but it isn't. He cares whether the object has zero _length_,
but for true polymorphism, he should be caring about whether the object is
_empty_. Not all empty objects have zero length, or even a length at all.
(E.g. binary trees.)
Conversely, not all objects that have length consider zero-length to be
false. Whether you test with "if a:" or "if len(a)>0", some objects
are going to be denied.

Thing is, objects that don't have length have almost no overlapping
uses with lists (i.e., you'd hardly ever write a function that could
take an int or a list, unless you type check the argument or use only
object protocol stuff like id and getattr, or pass it to another
function that does the same). Iterators do have overlapping uses with
lists, but the "if a:" doesn't work for them, so it's moot. OTOH,
objects that have length but don't consider zero-length to be false
(numpy arrays) do have overlapping uses with lists.

So, as a practical matter, I'd be inclined to side with Antoon on this
issue, even if it only increases polymorphism for certain people.

"if a:" almost never increases polymorphism because almost no
lengthless objects would work in that function anyways. Even if you
don't use numpy arrays, there's little practical benefit of "if a:"
except to save typing. If you do use numpy, it limits polymorphism.

"if len(a)>0" does increase polymorphism because it allows for objects
that have length but don't equate empty to false.

P.S. binary trees do have length: it's the number of nodes, just as the
number of keys is the length of a dict. I can't think of any objects
that use indexing but don't have a length, except for
poorly-implemented proxy objects. It's possible to define such types,
but would that be a Pythonic use of indexing?

Carl Banks

Oct 27 '06 #63
On 2006-10-27, Donn Cave <do**@u.washington.eduwrote:
In article <sl********************@rcpc42.vub.ac.be>,
Antoon Pardon <ap*****@forel.vub.ac.bewrote:
...
>I think you are incorrect.

Thanks! I rest my case!
>And how do I express that a number has to be greater than
100 into a Nothing vs Something dichotomy? Declare all
greater numbers as Something and the rest as Nothing?

Well, would you declare numbers less than 100 False?
No but the condition: x 100, will map all numbers to
either True or False. Can you provide a condition that will
provide a mapping to Nothing and Something? Without
artificially mapping False to Nothing and True to Something?
Think about it in more philosophical terms. What is Truth?
The Internet Encyclopedia of Philosophy may be some help
with this - http://www.iep.utm.edu/t/truth.htm
I don't care about such philosophical issues. I also
doubt that you could provide better answers if you
would subsituted Somthingness for truth is that text.
Then when you get tired of that, suppose that "if" and
"while" are asking for "yes" and "no", instead of "true"
and "false", and ask yourself if we have the philosophical
problems with "yes" that we do with "true".
Of course we have. Deciding whether a statment/condition is true
or not is equivallent to deciding whether or not we should answer
yes or no to a related question.

--
Antoon Pardon
Oct 27 '06 #64
On Fri, 27 Oct 2006 11:25:09 -0700
Carl Banks <pa************@gmail.comwrote:

#P.S. binary trees do have length: it's the number of nodes, just as
#the number of keys is the length of a dict. I can't think of any
#objects that use indexing but don't have a length,

Well, infinite lists (either circular or dynamically-growing) would be
one (unless you consider infinity to be a valid value of length, of
course).

Dictionaries with default value would be another (of course, Python 2.5
defaultdict *does* have length, but I would claim it is a wart).

But I agree those are pathological cases.

--
Best wishes,
Slawomir Nowaczyk
( Sl***************@cs.lth.se )

Programmer - A red-eyed, mumbling mammal
capable of conversing with inanimate objects.

Oct 27 '06 #65
I do see how mapping to Truth/Falsehood is more natural, and I do
believe that one of the great things about python is that it feels
natural in so many ways, and hence makes it easy to produce code, but
the one thing that Ms. Creighton points out that I can't get past is
that Python, even with its bool type, *still* evaluates somethingness
and nothingness, and True and False are just numbers with hats on.
>>True + 3
4
>>bool(True-1)
False
>>bool(True-2)
True
>>(10 5) + (10 < 5)
1

So when you say
>>>if 10 5:
.... print "Yes!"

Python is not evaluating the truth of the matter, but, as Ms. Creighton
would say, the "somethingness" of that which 10 5 evaluates to. (1
aka True)

Furthermore, how do you explain this bizarreness in terms of "Truth" and
"Falsehood?" You have to go back to the fact that True=1 and that
REALLY, Python is dealing with somethingness and nothingness. It might
not be as direct a mental connection as True/False, but it is certainly
a more accurate one for understanding how Python works.
>>(1 0) < 1
False
>>1 0 < 1
True
>>1 (0 < 1)
False
>>10 (0 < 1)
True

Finally, while True/False is a good mental mapping for numeric
comparisons, take the following:
>>if "Cliff is a pillar of the open source community":
.... print "thank you"
.... else:
.... print "bugger off"

bugger off

Clearly this is not true. (Google Cliff/Dyer open source: only 11
hits.), but the string is *something* so the if block gets evaluated.

Cheers,
Cliff
Oct 27 '06 #66
J. Clifford Dyer wrote:
I do see how mapping to Truth/Falsehood is more natural, and I do
believe that one of the great things about python is that it feels
natural in so many ways, and hence makes it easy to produce code, but
the one thing that Ms. Creighton points out that I can't get past is
that Python, even with its bool type, *still* evaluates somethingness
and nothingness, and True and False are just numbers with hats on.
>>True + 3
4
>>bool(True-1)
False
>>bool(True-2)
True
>>(10 5) + (10 < 5)
1

So when you say
>>>if 10 5:
.... print "Yes!"
Seems pretty clear to me that the situations you discuss above involve
numeric coercions of a Boolean value.
Python is not evaluating the truth of the matter, but, as Ms. Creighton
would say, the "somethingness" of that which 10 5 evaluates to. (1
aka True)
>>type(10>5)
<type 'bool'>
>>>
It does seem that there is a specific type associated with the result of
a comparison, even though you would really like to to be "a number with
a hat on".
Furthermore, how do you explain this bizarreness in terms of "Truth" and
"Falsehood?" You have to go back to the fact that True=1 and that
REALLY, Python is dealing with somethingness and nothingness. It might
not be as direct a mental connection as True/False, but it is certainly
a more accurate one for understanding how Python works.
>>(1 0) < 1
False
>>1 0 < 1
True
>>1 (0 < 1)
False
>>10 (0 < 1)
True
I have no idea what you think that you are demonstrating here.
Finally, while True/False is a good mental mapping for numeric
comparisons, take the following:
>>if "Cliff is a pillar of the open source community":
.... print "thank you"
.... else:
.... print "bugger off"

bugger off

Clearly this is not true. (Google Cliff/Dyer open source: only 11
hits.), but the string is *something* so the if block gets evaluated.
>>if "The above example was bollocks":
... print "You don't know what you are talking about"
... else:
... print "Sorry: of course you are perfectly correct"
...
You don't know what you are talking about
>>>
regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Oct 28 '06 #67
At Friday 27/10/2006 23:13, Steve Holden wrote:
>J. Clifford Dyer wrote:
the one thing that Ms. Creighton points out that I can't get past is
that Python, even with its bool type, *still* evaluates somethingness
and nothingness, and True and False are just numbers with hats on.
>>True + 3
4
>>bool(True-1)
False
>>bool(True-2)
True
>>(10 5) + (10 < 5)
1
Seems pretty clear to me that the situations you discuss above involve
numeric coercions of a Boolean value.
A "true" Boolean value should not be coerced into any other thing.
True+1 is as meaningless as "A"+1, or even "1"+1. The fact is, bool
is just an integer in disguise.
I always regretted that Python just went mid-way moving onto a true
Boolean type; I'd prefer it to stay as it was before bool was introduced.
Python is not evaluating the truth of the matter, but, as Ms. Creighton
would say, the "somethingness" of that which 10 5 evaluates to. (1
aka True)
>>type(10>5)
<type 'bool'>
>>>
>>bool.__mro__
(<type 'bool'>, <type 'int'>, <type 'object'>)
>It does seem that there is a specific type associated with the result of
a comparison, even though you would really like to to be "a number with
a hat on".
It *is* an integer with a hat on.
>>isinstance(True,int)
True
--
Gabriel Genellina
Softlab SRL

__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam ¡gratis!
¡Abrí tu cuenta ya! - http://correo.yahoo.com.ar
Oct 28 '06 #68
On Sat, 28 Oct 2006 03:13:42 +0100, Steve Holden wrote:

>Python is not evaluating the truth of the matter, but, as Ms. Creighton
would say, the "somethingness" of that which 10 5 evaluates to. (1
aka True)
>>type(10>5)
<type 'bool'>
>>>

It does seem that there is a specific type associated with the result of
a comparison, even though you would really like to to be "a number with
a hat on".
Python bools really are subclassed from ints:
>>issubclass(bool, int)
True

They are ints wearing a Boolean hat. This was a controversial compromise.

> >>(1 0) < 1
False
> >>1 0 < 1
True
> >>1 (0 < 1)
False
> >>10 (0 < 1)
True
I have no idea what you think that you are demonstrating here.
Run through the expressions by hand:

(1 0) < 1
True < 1
False

The mere fact that you can compare bools with ints demonstrates that
Python bools aren't "real" Booleans.

>Finally, while True/False is a good mental mapping for numeric
comparisons, take the following:
> >>if "Cliff is a pillar of the open source community":
.... print "thank you"
.... else:
.... print "bugger off"

bugger off

Clearly this is not true. (Google Cliff/Dyer open source: only 11
hits.), but the string is *something* so the if block gets evaluated.
>>if "The above example was bollocks":
... print "You don't know what you are talking about"
... else:
... print "Sorry: of course you are perfectly correct"
...
You don't know what you are talking about
Cliff is making a point about semantics, and he's absolutely correct about
it, although it is irrelevant since we're talking about two-value logic
not semantics.


--
Steven.

Oct 28 '06 #69
On Fri, 27 Oct 2006 17:35:58 +0000, Antoon Pardon wrote:
On 2006-10-27, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:
>But in this specific instance, I don't see any advantage to explicitly
testing the length of a list. Antoon might think that is sufficiently
polymorphic, but it isn't. He cares whether the object has zero _length_,
but for true polymorphism, he should be caring about whether the object is
_empty_. Not all empty objects have zero length, or even a length at all.
(E.g. binary trees.) That's why Python classes can use a __nonzero__
method, falling back on __len__ only if __nonzero__ is not defined.

Nobody can force you to write a container class that also provides a
__len__ method. But if you don't provide one then IMO it is your class
that deviates from standard practice. Mathematically, sets and
directories have no length either, yet the len function does provide
an answer if you give it a set or directory as an argument.
Do you mean dictionary?

Dictionaries, a.k.a. hash tables, aren't a standard mathematical data
type. Even if they were, they have two "lengths" (size really): the size
of the table, and the number of items in the table. In a high level
language like Python, you don't care about the size of the table (since it
will, I believe, automatically grow dynamically if you need it to), so
number of items is the only "size" (length) you could care about.

So
it seems that python has generalised the len function to provide
the number of elements in the container.
Sure. But what about a container where the number of elements isn't
well-defined, e.g. iterators? Or something like a binary tree, where
counting the number of items is relatively expensive, but telling whether
it is empty or not is cheaper than dirt?

Here's a real example: it can be expensive to count the number of files in
a directory -- on my PC, it takes almost a third of a second to count a
mere 15,000 files in a single directory. (There may be a more sensible
way of counting the number of files under Linux than ls | wc -l, but if
so I don't know it.) But why slog through 15,000 files if all you need to
know is if the directory is empty or not? As soon as you see one file, you
know it isn't empty. Stop counting! Who cares whether there is one file or
15,000 files?
I have written a Tree class(*). It can be used as a drop in replacement
anywhere where a directory is used, as long as there is a full order
relationship in the key domain. That tree class provides a __len__
method that will anser with the number of items in the tree just
as a directory would and I see nothing wrong with that.
And I'm happy for you. But imagine a container object that maps a URL to
some piece of data fetched from the Internet. Counting the size of the
Internet is infeasible -- even if you were willing to try, it could take
*weeks* of computation to determine! But one can certainly tell if there
is an Internet out there or not. Such an object would always be True,
unless you had lost network connectivity.

My container object will work perfectly well with "if internet" but not
with "if len(internet) 0". You could even iterate over it, sort
of, by following links from one site to another.

But why are you checking the length of a container before iterating over
it? If you are writing something like this:

if len(container) != 0:
for item in container:
do_something()

then just stop it!
Of course I can't account for all possible ways someone wishes to
write a class, but I don't see what is wrong with counting on
the fact that an empty container has a length of zero.
Because you shouldn't assume containers have well-defined lengths unless
you actually care about the length, and you shouldn't assume that length
of zero implies "nothing to see here" unless you *know* that this is the
case. You should leave defining empty up to the container class itself.
Otherwise, you might be right 99 times in a hundred, but that hundredth
time will bite you.

I can write a container class where the truth value of an object
is independent of whether or not the object is empty and then
the "if obj:" idiom will fail to provide true polymorphism too.
A class that deliberate breaks the semantics of Python truth testing just
for the sake of breaking code really is a pathological case. Polymorphism
doesn't mean "will work with anything without exception".
--
Steve.

Oct 28 '06 #70
On Fri, 27 Oct 2006 18:22:28 +0000, Antoon Pardon wrote:
>>And how do I express that a number has to be greater than
100 into a Nothing vs Something dichotomy? Declare all
greater numbers as Something and the rest as Nothing?

Well, would you declare numbers less than 100 False?

No but the condition: x 100, will map all numbers to
either True or False. Can you provide a condition that will
provide a mapping to Nothing and Something? Without
artificially mapping False to Nothing and True to Something?
A B maps to max(0, A-B)

or more verbosely, "Remove B items from A items, stopping when there are
no more items to remove. What is left over? Something or Nothing?"

Likewise, A < B maps to max(0, B-A).

--
Steven.

Oct 28 '06 #71
On Fri, 27 Oct 2006 11:25:09 -0700, Carl Banks wrote:
Steven D'Aprano wrote:
>But in this specific instance, I don't see any advantage to explicitly
testing the length of a list. Antoon might think that is sufficiently
polymorphic, but it isn't. He cares whether the object has zero _length_,
but for true polymorphism, he should be caring about whether the object is
_empty_. Not all empty objects have zero length, or even a length at all.
(E.g. binary trees.)

Conversely, not all objects that have length consider zero-length to be
false.
Which is why truth-testing is defined by __nonzero__ with __len__ only the
fall-back, for convenience.
Whether you test with "if a:" or "if len(a)>0", some objects
are going to be denied.
If a class doesn't define __nonzero__ or __len__, it should. Unless it is
meant to always be True.

Thing is, objects that don't have length have almost no overlapping
uses with lists (i.e., you'd hardly ever write a function that could
take an int or a list, unless you type check the argument or use only
object protocol stuff like id and getattr, or pass it to another
function that does the same). Iterators do have overlapping uses with
lists, but the "if a:" doesn't work for them, so it's moot.
Sure it works for iterators.
>>it = iter([0])
bool(it)
True
>>it.next()
0
>>bool(it)
False

Perhaps this behaviour has changed in version 2.5, if so, I'd like to hear
the rationalisation before I declare it a mistake.

P.S. binary trees do have length: it's the number of nodes, just as the
number of keys is the length of a dict.
I don't know what you were taught, but I was taught that binary trees have
height and breadth. "Length" was never used for the number of nodes. If
you go to the trouble of walking the tree, you obviously get the
equivalent of a list with a length, but in all the texts I've read,
walking the entire tree is the classic example of an expensive operation
that you should try to avoid if you don't need to. The same goes for
counting the number of nodes, unless you wanted to cache the result
somewhere.

--
Steven.

Oct 28 '06 #72
In <pa****************************@REMOVE.THIS.cybers ource.com.au>, Steven
D'Aprano wrote:
On Fri, 27 Oct 2006 11:25:09 -0700, Carl Banks wrote:
>Iterators do have overlapping uses with lists, but the "if a:" doesn't
work for them, so it's moot.

Sure it works for iterators.
>>>it = iter([0])
bool(it)
True
>>>it.next()
0
>>>bool(it)
False
It works for *this* iterator. By accident.

Ciao,
Marc 'BlackJack' Rintsch
Oct 28 '06 #73
Steven D'Aprano wrote:
On Fri, 27 Oct 2006 11:25:09 -0700, Carl Banks wrote:
Steven D'Aprano wrote:
But in this specific instance, I don't see any advantage to explicitly
testing the length of a list. Antoon might think that is sufficiently
polymorphic, but it isn't. He cares whether the object has zero _length_,
but for true polymorphism, he should be caring about whether the object is
_empty_. Not all empty objects have zero length, or even a length at all.
(E.g. binary trees.)
Conversely, not all objects that have length consider zero-length to be
false.

Which is why truth-testing is defined by __nonzero__ with __len__ only the
fall-back, for convenience.
Not all objects that have a state of emptiness consider emptiness to be
false.

Whether you test with "if a:" or "if len(a)>0", some objects
are going to be denied.

If a class doesn't define __nonzero__ or __len__, it should.
No, it often shouldn't.

A. It's not always desirable for empty to be false. Numpy defines a
bunch of numeric array types that raise an exception when __nonzero__
(actually nb_nonzero in the C API) is called. This is the correct
behavior for numpy. It makes no sense for numpy arrays to be used in a
boolean context, but they certainly can be empty.

B. Sometimes it's impossible to determine the state of emptiness. For
example, iterators.

Thing is, objects that don't have length have almost no overlapping
uses with lists (i.e., you'd hardly ever write a function that could
take an int or a list, unless you type check the argument or use only
object protocol stuff like id and getattr, or pass it to another
function that does the same). Iterators do have overlapping uses with
lists, but the "if a:" doesn't work for them, so it's moot.

Sure it works for iterators.
>it = iter([0])
bool(it)
True
>it.next()
0
>bool(it)
False

Perhaps this behaviour has changed in version 2.5, if so, I'd like to hear
the rationalisation before I declare it a mistake.
You haven't been paying attention.

Yes, this behavior has been changed in 2.5. The built-in iterators
always return True in 2.5. But even in 2.4, it was not true for
iterators in general:
>>a = []
bool(x for x in a)
True

At no point could you count on an iterator returning False for empty,
unless you'd made it yourself. Neither "if a:" nor "if len(a)>0" is a
valid test for an empty iterator.

P.S. binary trees do have length: it's the number of nodes, just as the
number of keys is the length of a dict.

I don't know what you were taught, but I was taught that binary trees have
height and breadth.
It doesn't really matter. dicts and sets don't have a length, either.
Or if they do, it's the length of the hash table, not the number of
entries. Weren't you taught that? But Python uses len() to get the
number of items in a container. Any Pythonic implementation of a
binary tree class would use len() to return the number of entries in
it. Anything that uses indexing ought to define len(), if it can.
Overall, your objections don't really apply, since you're arguing what
ought to be whereas my argument is pragmatic. Practically speaking, in
realistic situations, "if len(a)>0" will work for a wider range of
types than "if a:".
Carl Banks

Oct 28 '06 #74
J. Clifford Dyer wrote:
>>(1 0) < 1
False
>>1 0 < 1
True
>>1 (0 < 1)
False
>>10 (0 < 1)
True
I hope you know why this works the way it does.

Georg
Oct 28 '06 #75
On Sat, 28 Oct 2006 11:42:42 +0200, Marc 'BlackJack' Rintsch wrote:
In <pa****************************@REMOVE.THIS.cybers ource.com.au>, Steven
D'Aprano wrote:
>On Fri, 27 Oct 2006 11:25:09 -0700, Carl Banks wrote:
>>Iterators do have overlapping uses with lists, but the "if a:" doesn't
work for them, so it's moot.

Sure it works for iterators.
>>>>it = iter([0])
bool(it)
True
>>>>it.next()
0
>>>>bool(it)
False

It works for *this* iterator. By accident.
Blimey, you're right. That can't be good.

In fact, it made a certain BDFL pretty mad:

http://mail.python.org/pipermail/pyt...er/056594.html

Okay, so all iterators are intentionally *supposed* to be True, always,
even if they are exhausted. As Guido says, don't treat iterators as
containers.

Fair enough.
--
Steven.

Oct 28 '06 #76
On 2006-10-28, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:
On Fri, 27 Oct 2006 18:22:28 +0000, Antoon Pardon wrote:
>>>And how do I express that a number has to be greater than
100 into a Nothing vs Something dichotomy? Declare all
greater numbers as Something and the rest as Nothing?

Well, would you declare numbers less than 100 False?

No but the condition: x 100, will map all numbers to
either True or False. Can you provide a condition that will
provide a mapping to Nothing and Something? Without
artificially mapping False to Nothing and True to Something?

A B maps to max(0, A-B)

or more verbosely, "Remove B items from A items, stopping when there are
no more items to remove. What is left over? Something or Nothing?"
This mapping no longer works if you are not working with numbers.
>>A = [1,2]
B = [3]
A B
False
>>max(0, A - B)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for -: 'list' and 'list'

--
Antoon Pardon
Oct 28 '06 #77
On 2006-10-28, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:
On Fri, 27 Oct 2006 17:35:58 +0000, Antoon Pardon wrote:
>On 2006-10-27, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:

So
it seems that python has generalised the len function to provide
the number of elements in the container.

Sure. But what about a container where the number of elements isn't
well-defined, e.g. iterators?
I see you already discovered iterators won't help you here.
Or something like a binary tree, where
counting the number of items is relatively expensive, but telling whether
it is empty or not is cheaper than dirt?
Counting the items in a binary tree and a dictionary are about equally
expensive. I guess that in practice a count attribute will keep score.
Here's a real example: it can be expensive to count the number of files in
a directory -- on my PC, it takes almost a third of a second to count a
mere 15,000 files in a single directory. (There may be a more sensible
way of counting the number of files under Linux than ls | wc -l, but if
so I don't know it.) But why slog through 15,000 files if all you need to
know is if the directory is empty or not? As soon as you see one file, you
know it isn't empty. Stop counting! Who cares whether there is one file or
15,000 files?
I don't know why you consider this a real example. The only time I care
whether a dictionary is empty or not is if I want to remove it and in
that case it better to just try to remove the dictionary and catch
the exception. Testing for emptyness or counting files in a directory
isn't robust anyway. You never know whether or not some other process
created a new file or deleted one between the time you tested and
the moment
>I have written a Tree class(*). It can be used as a drop in replacement
anywhere where a directory is used, as long as there is a full order
relationship in the key domain. That tree class provides a __len__
method that will anser with the number of items in the tree just
as a directory would and I see nothing wrong with that.

And I'm happy for you. But imagine a container object that maps a URL to
some piece of data fetched from the Internet. Counting the size of the
Internet is infeasible -- even if you were willing to try, it could take
*weeks* of computation to determine! But one can certainly tell if there
is an Internet out there or not. Such an object would always be True,
unless you had lost network connectivity.
Indeed and you could loose connectivity between your testing for it and
making your first connection and your URL's turn bogus
My container object will work perfectly well with "if internet" but not
with "if len(internet) 0". You could even iterate over it, sort
of, by following links from one site to another.
And in what way exactly would this container object of yours be
compatible with code that would expect a list like object? I guess
not very much.
But why are you checking the length of a container before iterating over
it? If you are writing something like this:

if len(container) != 0:
for item in container:
do_something()

then just stop it!
The same goes for

if container:
for iten in container:
do_something()

If your are writing the above you should stop it just the same.
>Of course I can't account for all possible ways someone wishes to
write a class, but I don't see what is wrong with counting on
the fact that an empty container has a length of zero.

Because you shouldn't assume containers have well-defined lengths unless
you actually care about the length, and you shouldn't assume that length
of zero implies "nothing to see here" unless you *know* that this is the
case.
I think these assumptions are equivallent with assuming it is a
container.
You should leave defining empty up to the container class itself.
Otherwise, you might be right 99 times in a hundred, but that hundredth
time will bite you.
Just as your assumption will bite you in case of numpy arrays.
>I can write a container class where the truth value of an object
is independent of whether or not the object is empty and then
the "if obj:" idiom will fail to provide true polymorphism too.

A class that deliberate breaks the semantics of Python truth testing just
for the sake of breaking code really is a pathological case. Polymorphism
doesn't mean "will work with anything without exception".
I find that your idea of what a container can lack also against the
semantics of Python.

--
Antoon Pardon
Oct 28 '06 #78
Georg Brandl wrote:
J. Clifford Dyer wrote:
> >>(1 0) < 1
False
> >>1 0 < 1
True
> >>1 (0 < 1)
False
> >>10 (0 < 1)
True

I hope you know why this works the way it does.

Georg
Yes, I do understand why it works. I couldn't have crafted it if I
didn't, but my point is that the reason why it works is not explainable
if you believe that you are dealing with booleans. It's only
explainable if you recognize that you are actually dealing with
integers, and specifically, 1 and 0. So the something/nothing dichotomy
combined with an understanding of what the comparison operation REALLY
does (yield a 1 or a 0) helps you understand where your result came
from, while thinking in terms of true/false will mislead you.

Oct 28 '06 #79
J. Clifford Dyer wrote:
Georg Brandl wrote:
>J. Clifford Dyer wrote:
>> >>(1 0) < 1
False
>>1 0 < 1
True
>>1 (0 < 1)
False
>>10 (0 < 1)
True

I hope you know why this works the way it does.

Georg

Yes, I do understand why it works. I couldn't have crafted it if I
didn't, but my point is that the reason why it works is not explainable
if you believe that you are dealing with booleans.
Okay, but you should have left off the second example, because it has nothing
to do with the others.
It's only
explainable if you recognize that you are actually dealing with
integers, and specifically, 1 and 0. So the something/nothing dichotomy
combined with an understanding of what the comparison operation REALLY
does (yield a 1 or a 0) helps you understand where your result came
from, while thinking in terms of true/false will mislead you.
That's true. The only sensible thing to do, if you had "real" booleans, for
1 True, would be to raise an exception.

Georg
Oct 28 '06 #80
Steven D'Aprano wrote:
On Sat, 28 Oct 2006 03:13:42 +0100, Steve Holden wrote:
>>Finally, while True/False is a good mental mapping for numeric
comparisons, take the following:

>>if "Cliff is a pillar of the open source community":
.... print "thank you"
.... else:
.... print "bugger off"

bugger off
First off, even though nobody has called me on it, this example really
prints "thank you", not "bugger off". I got confused in my cutting and
pasting. Sorry about that.

>>Clearly this is not true. (Google Cliff/Dyer open source: only 11
hits.), but the string is *something* so the if block gets evaluated.

>>if "The above example was bollocks":
... print "You don't know what you are talking about"
... else:
... print "Sorry: of course you are perfectly correct"
...
You don't know what you are talking about

Cliff is making a point about semantics, and he's absolutely correct about
it, although it is irrelevant since we're talking about two-value logic
not semantics.

Thank you for the clarification Steven (D'Aprano). To a certain level,
I agree that semantics are important. I hesitated about including that
example in my post to begin with. However, my point, and hopefully I'll
be able to make it more clearly now, was that true/false is a useful way
to think regarding logical statements like x == 3, but that when you are
dealing with strings, or more accurately strings that represent
language, you really aren't talking about truth any more, because in
that context, truth cannot be divorced from semantics--somethingness, on
the other hand, can.

Conceptually, you have to go through "'something' is true, and 'nothing'
is false" before it makes sense.

On the other hand, (to play devil's advocate for a moment), when you are
dealing with comparison operators, you have to go through "true
statements yield something and false statements yield nothing" before it
makes sense, or rather "yield a nothing value." So either way you think
about it, you have to, in some cases, mentally convert from truthiness
to somethingness or vice versa. I don't find it as odious to mentally
convert the comparison operators as I do the declarative statements. I
don't think it's just a personal preference either, because that way
your mental processes are in sync with the way python works. It
evaluates if the statement is true and yields a something value, and a
nothing value if it's false. You are working with the Tao of Python, if
you'll forgive the analogy. However thinking in terms of truth and then
saying that all statements that exist are true works, but runs counter
to what is going on behind the scenes.

Or maybe it doesn't, if everything's getting converted implicitly to
bool anyway. Maybe it is just personal preference after all. But then
bools are assigned "something" and "nothing" values....

This stuff is tricky, but I'm enjoying trying to wrap my mind around it,
and appreciating the comments and critiques.

Cheers,
Cliff
Oct 28 '06 #81
On Sat, 28 Oct 2006 03:24:50 -0700, Carl Banks wrote:
Not all objects that have a state of emptiness consider emptiness to be
false.
In which case they should define __nonzero__ appropriately.

In which case, calling code that assumes that len(obj) is a substitute for
truth-testing will do the wrong thing.

Whether you test with "if a:" or "if len(a)>0", some objects are
going to be denied.

If a class doesn't define __nonzero__ or __len__, it should.

No, it often shouldn't.
Okay, I want to qualify my statement: if a class doesn't define
__nonzero__ or __len__, *and doesn't want the default Python behaviour of
all instances evaluating as True*, then they should.
A. It's not always desirable for empty to be false. Numpy defines a
bunch of numeric array types that raise an exception when __nonzero__
(actually nb_nonzero in the C API) is called. This is the correct
behavior for numpy. It makes no sense for numpy arrays to be used in a
boolean context, but they certainly can be empty.
And, appropriate to the class, numpy arrays raise an exception when
__nonzero__ is called -- just as they should.
B. Sometimes it's impossible to determine the state of emptiness. For
example, iterators.
Since Guido has ruled that the protocol is that all iterators are True,
there is no need for __nonzero__ since the default behaviour does the job.
[snip]
>Perhaps this behaviour has changed in version 2.5, if so, I'd like to
hear the rationalisation before I declare it a mistake.

You haven't been paying attention.

Yes, this behavior has been changed in 2.5. The built-in iterators
always return True in 2.5. But even in 2.4, it was not true for
iterators in general:
Yes, you are right. I was fooled by a coincidence.
At no point could you count on an iterator returning False for empty,
unless you'd made it yourself. Neither "if a:" nor "if len(a)>0" is a
valid test for an empty iterator.
Correct. Guido's decision is that iterators are always "Something" (that
is, True in a truth context) even if they are exhausted.

P.S. binary trees do have length: it's the number of nodes, just as
the number of keys is the length of a dict.

I don't know what you were taught, but I was taught that binary trees
have height and breadth.

It doesn't really matter. dicts and sets don't have a length, either.
Or if they do, it's the length of the hash table, not the number of
entries. Weren't you taught that? But Python uses len() to get the
number of items in a container. Any Pythonic implementation of a binary
tree class would use len() to return the number of entries in it.
Anything that uses indexing ought to define len(), if it can.
In the binary tree:

tree -- A
A.left --B, A.right --C

what's tree[0]? Should it be A (preorder), or B (inorder) or C (postorder)?

Overall, your objections don't really apply, since you're arguing what
ought to be whereas my argument is pragmatic. Practically speaking, in
realistic situations, "if len(a)>0" will work for a wider range of types
than "if a:".
Well, that's a quantitative claim you're making there. Have you
actually gone through, say, the built in types and checked how many
have a length versus how many work in a truth-context?
>>import types
if types:
.... print "Modules work with bool"
....
Modules work with bool
>>if len(types)>0:
.... print "Modules work with len"
....
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: len() of unsized object

"if len(a)>0:" only works for objects that define __len__.

"if a:" works for any object that doesn't go to the trouble of
specifically prohibiting it, as numpy arrays deliberately do. That's the
Python way, and it is a deliberate design.
--
Steven.

Oct 28 '06 #82
Steven D'Aprano wrote:
On Sat, 28 Oct 2006 03:13:42 +0100, Steve Holden wrote:
>
>Finally, while True/False is a good mental mapping for numeric comparisons,
take the following:

if "Cliff is a pillar of the open source community":
.... print "thank you"
.... else:
.... print "bugger off"

bugger off

First off, even though nobody has called me on it, this example really prints
"thank you", not "bugger off". I got confused in my cutting and pasting.
Sorry about that.

>Clearly this is not true. (Google Cliff/Dyer open source: only 11 hits.),
but the string is *something* so the if block gets evaluated.

>>if "The above example was bollocks":
... print "You don't know what you are talking about"
... else:
... print "Sorry: of course you are perfectly correct"
...
You don't know what you are talking about
Cliff is making a point about semantics, and he's absolutely correct about
it, although it is irrelevant since we're talking about two-value logic
not semantics.
Cheers,
Cliff
I am joining after some network downtime here, so I seem to have missed what
the real issue here is. At the risk of being completely irrelevant to the
discussion here, I think it doesn't seem to be just about something or
nothing - is None something or nothing? It seems to be neither:
>>None
None and True
None or True
True
>>None and False
None or False
False
>>False or None
False and None
False
>>True and None
True or None
True
>>not None
True

Chetan
Oct 29 '06 #83
Gabriel Genellina <ga******@yahoo.com.arwrites:
At Friday 27/10/2006 23:13, Steve Holden wrote:
>>J. Clifford Dyer wrote:
the one thing that Ms. Creighton points out that I can't get past is
that Python, even with its bool type, *still* evaluates somethingness
and nothingness, and True and False are just numbers with hats on.

>>True + 3
4
>>bool(True-1)
False
>>bool(True-2)
True
>>(10 5) + (10 < 5)
1
Seems pretty clear to me that the situations you discuss above involve
numeric coercions of a Boolean value.

A "true" Boolean value should not be coerced into any other thing. True+1 is as
meaningless as "A"+1, or even "1"+1. The fact is, bool is just an integer in
disguise.
I always regretted that Python just went mid-way moving onto a true Boolean
type; I'd prefer it to stay as it was before bool was introduced.
Python is not evaluating the truth of the matter, but, as Ms. Creighton
would say, the "somethingness" of that which 10 5 evaluates to. (1
aka True)

>>type(10>5)
<type 'bool'>
> >>>
>>>bool.__mro__
(<type 'bool'>, <type 'int'>, <type 'object'>)
>>It does seem that there is a specific type associated with the result of
a comparison, even though you would really like to to be "a number with
a hat on".

It *is* an integer with a hat on.
>>>isinstance(True,int)
True
This has focussed on the relational operators, which seem to produce a number
with a hat on. However, logical operations do not do so.
True and "This string" produces "This string", for example.

This is hardly surprising, though.
The way they are defined, booleans seem to be the syntactic sugar that some
people like. Many of the projects that I have been associated with had such
a define because the language (C) does not provide it. On the other hand,
there are many who do just fine without them.

For expressions used in control flow, if the expression somehow produces a 0
(False included) or None, the behavior is as if the expression is false.
Confusion may arise because the way that answer is produced may not be
immediately obvious. For constructs such as "if obj:" the answer depends on
which methods the object has defined and what the state of the object is at the
time, but this has nothing to do with whether the answer that was produced was
strictly a boolean or not.

Chetan
>

--
Gabriel Genellina
Softlab SRL

__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam ¡gratis! ¡Abrí tu cuenta
ya! - http://correo.yahoo.com.ar
Oct 29 '06 #84
Chetan wrote:
>Steven D'Aprano wrote:
On Sat, 28 Oct 2006 03:13:42 +0100, Steve Holden wrote:

Finally, while True/False is a good mental mapping for numeric comparisons,
take the following:

>>if "Cliff is a pillar of the open source community":
.... print "thank you"
.... else:
.... print "bugger off"

bugger off

First off, even though nobody has called me on it, this example really prints
"thank you", not "bugger off". I got confused in my cutting and pasting.
Sorry about that.

>>Clearly this is not true. (Google Cliff/Dyer open source: only 11 hits.),
but the string is *something* so the if block gets evaluated.

>>if "The above example was bollocks":
... print "You don't know what you are talking about"
... else:
... print "Sorry: of course you are perfectly correct"
...
You don't know what you are talking about
Cliff is making a point about semantics, and he's absolutely correct about
it, although it is irrelevant since we're talking about two-value logic
not semantics.
Cheers,
Cliff

I am joining after some network downtime here, so I seem to have missed what
the real issue here is. At the risk of being completely irrelevant to the
discussion here, I think it doesn't seem to be just about something or
nothing - is None something or nothing? It seems to be neither:
If is, of course, nothing. You may have misunderstood the semantics of the
"and" and "or" operators.
>>>None
None and True
None or True
True
>>>None and False
None or False
False
>>>False or None
False and None
False
>>>True and None
True or None
True
>>>not None
True
x and y | x something | x nothing
---------------------------------------
y something | y | x
y nothing | y | x

x or y | x something | x nothing
---------------------------------------
y something | x | y
y nothing | x | y
Georg
Oct 29 '06 #85
Georg Brandl <g.*************@gmx.netwrites:
Chetan wrote:
>>Steven D'Aprano wrote:
On Sat, 28 Oct 2006 03:13:42 +0100, Steve Holden wrote:
>
Finally, while True/False is a good mental mapping for numeric comparisons,
take the following:

>>if "Cliff is a pillar of the open source community":
.... print "thank you"
.... else:
.... print "bugger off"

bugger off
First off, even though nobody has called me on it, this example really prints
"thank you", not "bugger off". I got confused in my cutting and pasting.
Sorry about that.
Clearly this is not true. (Google Cliff/Dyer open source: only 11 hits.),
but the string is *something* so the if block gets evaluated.

>>if "The above example was bollocks":
... print "You don't know what you are talking about"
... else:
... print "Sorry: of course you are perfectly correct"
...
You don't know what you are talking about
Cliff is making a point about semantics, and he's absolutely correct about
it, although it is irrelevant since we're talking about two-value logic
not semantics.
Cheers,
Cliff

I am joining after some network downtime here, so I seem to have missed what
the real issue here is. At the risk of being completely irrelevant to the
discussion here, I think it doesn't seem to be just about something or
nothing - is None something or nothing? It seems to be neither:

If is, of course, nothing. You may have misunderstood the semantics of the
"and" and "or" operators.
I have not. I just posted another message on the subject. All I am trying to
point out is that the "nothingness" evaluation does not occur at the level of
expressions. It is only when the expression is needed to make decisions about
control flow that this comes into picture.
>>>>None
None and True
None or True
True
>>>>None and False
None or False
False
>>>>False or None
False and None
False
>>>>True and None
True or None
True
>>>>not None
True

x and y | x something | x nothing
---------------------------------------
y something | y | x
y nothing | y | x

x or y | x something | x nothing
---------------------------------------
y something | x | y
y nothing | x | y
Georg
Oct 29 '06 #86
Steven D'Aprano wrote:
Carl Banks:
Overall, your objections don't really apply, since you're arguing what
ought to be whereas my argument is pragmatic. Practically speaking, in
realistic situations, "if len(a)>0" will work for a wider range of types
than "if a:".

Well, that's a quantitative claim you're making there. Have you
actually gone through, say, the built in types and checked how many
have a length versus how many work in a truth-context?
No, and it's irrelevant to my argument.

For some reason, people seem to think it's absolutely wonderful that
you can write "if X:" somewhere, and that this "works" whether X is a
list or an int or any other object, as if "working" for both ints and
lists was actually useful.

Well, it's not.

You see, presumably you have to do something with X. And in realistic
code, there's not a lot of stuff you can do with that works for both
container types like lists and dict, and atomic types like ints and
floats. All you could do is call generic object protocol stuff like
id() or str(). There's some odd operations that can work for both a
container and an atomic (addition); even so, it's rare that a given
piece of code would actually be useful for both containers and atomics.
(I mean, you could pass lists into a function such as the following,
but would it be useful?)

def binomial3(a,b,c,d):
return a + 3*b + 3*c + d

What I'm saying is, the fact that "if X:" "works" for almost any type
is big ol' red herring. The only thing that really matters is if it
works for types that _actually have some realistic overlapping uses_.

So let's do your little exercise keeping that in mind. Let's look at
realistic uses of containers. Suppose we have a function such as this:

def f(X):
if not X:
return
do_some_indexing(X[2],X[4])

We see that we subscript X. Now, you can't subscript an int, so if
we're going to count number of types that support "if a:" versus the
number that support "if len(a)>0", we're not going to consider ints.
When deciding whether we should go with "if a:" or "if len(a)>0", we
should only count types that support indexing.

Objects that support indexing and work with "if a:":
lists,tuples,dicts,strings,xrange,collections.dequ e,array.array

Objects that support indexing and work with "if len(a)>0":
lists,tuples,dicts,strings,xrange,collections.dequ e,array.array ...
numpy arrays

Another thing containers do a lot is iteration.

Objects that support iteration and work with "if a:"
lists,tuples,dicts,sets,strings,xrange,collections .deque,array.array

Objects that support iteration and work with "if len(a)>0:"
lists,tuples,dicts,sets,strings,xrange,collections .deque,array.array
.... numpy arrays

What can we conclude? If you're indexing or iterating, "if a:" and "if
len(a)>0:" are equally successful for built-in types, but "if
len(a)>0:" also works for numpy arrays. If your only measure of
success is how many classes the emptiness tests works for, then "if
len(a)>0:" wins. This is just an example; we haven't looked at all
possible uses of containers. There will be a few cases where "if a:"
works but "if len(a)>0:" doesn't. But it should be pretty clear where
this is headed.

So the question is: Do you want use "if len(a)>0:", so that in a lot
of cases your code can also work if someone wants to use a popular
third party package? Or do you want to use "if a:", so that in rare
cases your code could also work with some builtin atomic types?
Carl Banks

Oct 29 '06 #87
Chetan wrote:
>>I am joining after some network downtime here, so I seem to have missed what
the real issue here is. At the risk of being completely irrelevant to the
discussion here, I think it doesn't seem to be just about something or
nothing - is None something or nothing? It seems to be neither:

If is, of course, nothing. You may have misunderstood the semantics of the
"and" and "or" operators.

I have not. I just posted another message on the subject. All I am trying to
point out is that the "nothingness" evaluation does not occur at the level of
expressions. It is only when the expression is needed to make decisions about
control flow that this comes into picture.
This is not correct. "and" and "or" involve truth (or "somethingness")
evaluation, as you can see from this example:

Python 2.5 (r25:51908, Sep 22 2006, 10:45:03)
>>class A:
.... def __nonzero__(self):
.... print "nonzero"
.... return True
....
>>A() and 1
nonzero
1
>>>
Georg
Oct 29 '06 #88
On Sun, 29 Oct 2006 00:31:23 -0700, Carl Banks wrote:
Steven D'Aprano wrote:
>Carl Banks:
Overall, your objections don't really apply, since you're arguing what
ought to be whereas my argument is pragmatic. Practically speaking, in
realistic situations, "if len(a)>0" will work for a wider range of types
than "if a:".

Well, that's a quantitative claim you're making there. Have you
actually gone through, say, the built in types and checked how many
have a length versus how many work in a truth-context?

No, and it's irrelevant to my argument.
And yet you not only made the claim in the first place, but you also spend
a good half or three quarters of your response justifying your claim. You
obviously didn't think it was irrelevant when you first made the claim,
and you clearly still don't think it was irrelevant now that you've spent
time checking an arbitrary set of types. Either way, you're still wrong.

"if a:" will work with EVERY TYPE except those few (the only one?) like
numpy arrays which deliberately raise an exception because they don't make
sense in a Boolean context. (And even then, arguably numpy is doing the
wrong thing: the Pythonic behaviour would be for numpy arrays to all
be True.)

"if len(a)>0:" can only work with types that have lengths. It is a logical
necessity that the number of types that have lengths must be no bigger
than the number of types in total, numpy arrays notwithstanding.
For some reason, people seem to think it's absolutely wonderful that
you can write "if X:" somewhere, and that this "works" whether X is a
list or an int or any other object, as if "working" for both ints and
lists was actually useful.

Well, it's not.

You see, presumably you have to do something with X. And in realistic
code, there's not a lot of stuff you can do with that works for both
container types like lists and dict, and atomic types like ints and
floats.
Who cares whether or not your function accepts mixed data types like lists
and floats? Why do you think it matters whether the one function has to
operate on both sequences and atomic types?

What *does* matter is that, regardless of whether you are operating on
sequences, mappings, numeric types, the same syntax works.

That's why (for example) Python allows + to operate on lists, or strings,
or floats -- but that doesn't imply that you can add a list to a float,
or that the same code will operate happily on both lists and floats. You,
the developer, don't need to care what data types you are adding, you just
use the same syntax: a+b. The objects themselves know what addition
means to themselves. In practice, string addition threatens to be so
inefficient that you might wish to avoid doing it, but as a general
principle, Python idioms and syntax are as type-independent as possible.

That's why obj[index] works whether you are getting or setting or deleting
an item, whether it is a sequence or a mapping or a custom class. As much
as possible, you don't need to know what the object is to know what syntax
to use. The idiom for item-access should always be obj[index], not
obj[index] for some types, obj.get(index) for some others, and
getitem(obj, index) for the rest.

(Custom classes are, of course, free to break these guidelines, just as
the numpy developers were free to have __nonzero__ raise an exception. One
hopes they have good reasons for doing so.)

And that's why Python not only allows but prefers "if any_object_at_all:"
over type-dependent tricks. The *object itself* is supposed to know
whether it is equivalent to true or false (or, in rare cases like numpy
arrays, raise an exception if truth-testing doesn't mean anything for the
type). You, the developer, are not supposed to spend your time wondering
how to recognise if the object is equivalent to false, you just ask the
object.

If some well-meaning person argued that the correct way to test for a
numeric value of zero/non-zero was like this:

if x*2 != x:
# x must be non-zero

you'd fall down laughing (at least, I hope you'd fall down laughing). Yes,
such a test works, but you'd be crazy to do such unnecessary work if all
you want to know if x was nonzero. (And beware of floating point rounding:
what if x is tiny?)

And then someone passes a class that implements infinity or the alephs to
this function (that could simply mean an INF float on a platform that
supports the IE standard) and the code wrongly decides that INF is zero.
Oops.

"if x == 0:" is better, but still not good enough, because you're
still making assumptions about the data type. What if it is a numeric type
that works with interval arithmetic? You don't know what the right way to
test for a False interval is -- but the interval class itself will know.

And that's the point -- you're making unnecessary assumptions about the
data, *and* doing unnecessary calculations based on those assumptions. At
best, you're wasting your time. At worst, you're introducing bugs.

It isn't often that I make an appeal to authority, but this is one of
them. No offense, but when it comes to language design its a brave or
foolish programmer who bucks the language idioms that Guido chose.

--
Steven.

Oct 29 '06 #89
Steven D'Aprano wrote:
It isn't often that I make an appeal to authority, but this is one of
them. No offense, but when it comes to language design its a brave or
foolish programmer who bucks the language idioms that Guido chose.
Well, it's pretty clear you consider some abstact notion of unity of
style more important than practical considerations of how your data is
used.

In that case you might as well just go with what the authority tells
you to.

(And hope that your users don't do much numerical stuff.)
Carl Banks

Oct 29 '06 #90
On 2006-10-29, Steven D'Aprano <st***@REMOVE.THIS.cybersource.com.auwrote:
On Sun, 29 Oct 2006 00:31:23 -0700, Carl Banks wrote:

That's why (for example) Python allows + to operate on lists, or strings,
or floats
That was IMO a mistake. There are types for which concatenation as well as
addition are meaningfull operators. By using the "+" for both these
operations, writing such a class becomes awkward in Python because you
have to stray away from Python idiom for one of the two operations.
Should Python have chosen the "_" character for concatenating writing
amnd working with such a class would have looked more natural.
-- but that doesn't imply that you can add a list to a float,
or that the same code will operate happily on both lists and floats. You,
the developer, don't need to care what data types you are adding, you just
use the same syntax: a+b.
Of course the developer needs to care. It's not because a+b will give
a result that the result will also be meaningfull. It is not because
a class has defined the operators "+", "-", "/", "*" it will give
a meaningfull result if you throw a matrix of instances into procdure
that solves equations.
The objects themselves know what addition
means to themselves. In practice, string addition threatens to be so
inefficient that you might wish to avoid doing it, but as a general
principle, Python idioms and syntax are as type-independent as possible.
Which isn't necesarrily a good thing. I think there is even a warning
somewhere against too easily overloading the arithmetic operators
for operations that don't act at all as such operators. I think
they should have thought of that before using "+" for concatenation.
That's why obj[index] works whether you are getting or setting or deleting
an item, whether it is a sequence or a mapping or a custom class. As much
as possible, you don't need to know what the object is to know what syntax
to use. The idiom for item-access should always be obj[index], not
obj[index] for some types, obj.get(index) for some others, and
getitem(obj, index) for the rest.

(Custom classes are, of course, free to break these guidelines, just as
the numpy developers were free to have __nonzero__ raise an exception. One
hopes they have good reasons for doing so.)

And that's why Python not only allows but prefers "if any_object_at_all:"
over type-dependent tricks. The *object itself* is supposed to know
whether it is equivalent to true or false
But the objects idea of true and false may not be the most usefull
distinction the programmer wants to make. Look at the following
example:

if container:
Prepare()
Treat(container)

Now Treat will throw an exception if container is not enough
list like. But that exception will be throw after Prepare has
done useless work in this case. If I replace "if container"
with "if len(container)" the exception will be thrown earlier.
So using "if len(container)" gives more usefull information
than a simple "if container".
(or, in rare cases like numpy
arrays, raise an exception if truth-testing doesn't mean anything for the
type). You, the developer, are not supposed to spend your time wondering
how to recognise if the object is equivalent to false, you just ask the
object.

If some well-meaning person argued that the correct way to test for a
numeric value of zero/non-zero was like this:

if x*2 != x:
# x must be non-zero

you'd fall down laughing (at least, I hope you'd fall down laughing). Yes,
such a test works, but you'd be crazy to do such unnecessary work if all
you want to know if x was nonzero. (And beware of floating point rounding:
what if x is tiny?)

And then someone passes a class that implements infinity or the alephs to
this function (that could simply mean an INF float on a platform that
supports the IE standard) and the code wrongly decides that INF is zero.
Oops.

"if x == 0:" is better, but still not good enough, because you're
still making assumptions about the data type. What if it is a numeric type
that works with interval arithmetic? You don't know what the right way to
test for a False interval is -- but the interval class itself will know.
But you have no idea that the interval of "False" will guide you to the
right branch. And inteval class might treat all zero length intervals
as False or it could have a special empty interval which would be the
only False interval. Both could be argued for, but you would want to
know which before you would rely on "if some_interval:" to guide
you to the right branch.
And that's the point -- you're making unnecessary assumptions about the
data, *and* doing unnecessary calculations based on those assumptions. At
best, you're wasting your time. At worst, you're introducing bugs.
You have to make assumptions anyway. And your kind of code could
introduce bugs just the same.
It isn't often that I make an appeal to authority, but this is one of
them. No offense, but when it comes to language design its a brave or
foolish programmer who bucks the language idioms that Guido chose.
You don't have to be that brave to go against Guido's autority. It
is only recently he introduced a ternary operator and then only after
someone in the development group was hit by a bug introduced by the
then supported idiom. Python is a nice enough language with a high
quality in design. Yet it still has its warts. So I see no
reason to blindly follow the autority of its designers.

--
Antoon Pardon
Oct 30 '06 #91

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

23
5986
by: hedylogus | last post by:
I've just begun learning C++ and I'm trying to write a program to shuffle a deck of cards. I've succeeded....for the most part....but every now and then rand() produces duplicate random numbers...
38
5002
by: Shaun McKinnon | last post by:
HI...Here's my problem...I have a popup window that loads when i want it to, but it's not sized properly. I've set the size, but it doesn't seem to work. I've been on 8 different websites to find...
5
2655
by: Sue | last post by:
After finishing up my first quarter JavaScript on 12/12/03, I decided to improve character checking on my project. In my project I only had to do very basic validation. Therefore, I only had one...
22
1924
by: James H. | last post by:
Greetings! I'm new to Python and am struggling a little with "and" and "or" logic in Python. Since Python always ends up returning a value and this is a little different from C, the language I...
14
1808
by: Mr Newbie | last post by:
I am often in the situation where I want to act on the result of a function, but a simple boolean is not enough. For example, I may have a function called isAuthorised ( User, Action ) as ?????...
18
2835
by: Nobody | last post by:
I've been looking for a job for a while now, and have run into this interview question twice now... and have stupidly kind of blown it twice... (although I've gotten better)... time to finally...
4
2871
by: RobG | last post by:
I have always accessed attributes such as disabled using the DOM element property, however I was wondering about implementing a more generic function to get the values of attributes - which of...
2
1279
by: cbmeeks | last post by:
Man, I realize I've been asking a lot of questions lately. I appreciate you guys helping me in my thought process. This time, I have a design question I want opinions on. I'm building a...
1
1845
by: deanchhsw | last post by:
Part A (http://bytes.com/topic/java/insights/645821-sudoku) B (http://bytes.com/topic/java/insights/739704-sudoku-b) C (http://bytes.com/topic/java/insights/739703-sudoku-c) this question refers...
0
7093
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7353
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
7011
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7468
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5596
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5023
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3170
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1521
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
747
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.