question about True values

C

Carl Banks

Good advice, because on 2.5 it's True again.

Doesn't this fall under "any empty sequence" in the following list of
evaluates-to-false:

Nope. An iterator is not a sequence, and it's impossible to determine
whether an iterator is "empty" in general, except by trying to get an
item from it. So even in 2.4.3 some "empty" iterators return True:
True

The only reasonable advice is to avoid the direct boolean test ("if
a:") altogether if you want to support iterators.

Unfortunately, iterators and lists have a lot of overlapping use, and
it's very common to test for emptiness of lists using "if a:". If one
tries to use an iterator where a list is expected it could lead to a
silent failure.

IMO, this is big time wart in the language. Iterators have no
calculatable truth value; for many other types a truth value doesn't
make sense (for instance: function objects, type objects, modules,
user-defined types that don't bother with __nonzero__). Using such
objects in a boolean context is almost always an error. Objects of
these types should raise exceptions when used as a boolen. numpy
arrays wisely already do this.

(I'll stop short of mentioning that, because neither numpy arrays nor
iterators consider "empty" to be "false", the idea that "empty" is
"false" is very far from self-evident; therefore lists, tuples, dicts,
and sets should also raise exceptions when used as a boolean. I won't
mention that, though.)


Carl Banks
 
B

Ben Finney

Carl Banks said:
An iterator is not a sequence, and it's impossible to determine
whether an iterator is "empty" in general, except by trying to get
an item from it. [...]

IMO, this is big time wart in the language. Iterators have no
calculatable truth value; for many other types a truth value doesn't
make sense (for instance: function objects, type objects, modules,
user-defined types that don't bother with __nonzero__). Using such
objects in a boolean context is almost always an error.

It still seems like a reasonable thing for a programmer to do though,
even if the language doesn't currently support it.

Would it make sense to *define* a truth value for iterators? Or at
least to enable those that *are* able to say "I'm empty" to do so in a
way that boolean contexts can interpret as "false"?

Perhaps allowing (but not requiring) an iterator object to grow a
'len' method is the simplest way.
 
R

Robert Kern

Ben said:
Would it make sense to *define* a truth value for iterators? Or at
least to enable those that *are* able to say "I'm empty" to do so in a
way that boolean contexts can interpret as "false"?

Perhaps allowing (but not requiring) an iterator object to grow a
'len' method is the simplest way.

And indeed, they are already allowed to do so.

Python 2.4.1 (#2, Mar 31 2005, 00:05:10)
Type "copyright", "credits" or "license" for more information.

In [1]: len(iter(()))
Out[1]: 0

In [2]: bool(iter(()))
Out[2]: False

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

Carl Banks

Ben said:
Carl Banks said:
An iterator is not a sequence, and it's impossible to determine
whether an iterator is "empty" in general, except by trying to get
an item from it. [...]

IMO, this is big time wart in the language. Iterators have no
calculatable truth value; for many other types a truth value doesn't
make sense (for instance: function objects, type objects, modules,
user-defined types that don't bother with __nonzero__). Using such
objects in a boolean context is almost always an error.

It still seems like a reasonable thing for a programmer to do though,
even if the language doesn't currently support it.

Would it make sense to *define* a truth value for iterators? Or at
least to enable those that *are* able to say "I'm empty" to do so in a
way that boolean contexts can interpret as "false"?

Again, it's impossible to tell if an iterator is empty in general
except by trying to get an item. You could add a feature to iterators
that fetches an item and stores it, but that would a. be a pain in the
neck for everyone, and b. adversely affect iterators that depend on
outside factors.
Perhaps allowing (but not requiring) an iterator object to grow a
'len' method is the simplest way.

I could live with some iterators defining __len__ or even __nonzero__,
as long as iterators that couldn't determine these things threw an
exception rather than returning a fake value. I'd rather no iterators
did this, though, because having these options makes it likely that
some programmers will write code supporting only "len-able iterators",
thus hindering polymorphism unnecessarily. I'd rather people use
iterators as iterators and not as temporally-challenged lists.

However, it's certainly helpful sometimes to know if an iterator has
any items left (say, to possibly avoid some initialization code). I
don't think this should be a part of iterator protocol, but maybe it'd
be nice if somewhere in the the standard library there was an iterator
type such as this:

class EmptySavvyIterator(object):
noitem = object()
def __init__(self,iterable):
self.iterator = iter(iterable)
self.storage = self.noitem
def __iter__(self):
return self
def next(self):
if self.storage is not self.noitem:
item = self.storage
self.storage = self.noitem
return item
return self.iterator.next()
def empty(self):
if self.storage is not self.noitem:
return False
try:
self.storage = self.iterator.next()
except StopIteration:
return True
return False
# if you must...
def __nonzero__(self):
return not self.empty()


Carl Banks
 
C

Carl Banks

Robert said:
Ben said:
Would it make sense to *define* a truth value for iterators? Or at
least to enable those that *are* able to say "I'm empty" to do so in a
way that boolean contexts can interpret as "false"?

Perhaps allowing (but not requiring) an iterator object to grow a
'len' method is the simplest way.

And indeed, they are already allowed to do so.

Python 2.4.1 (#2, Mar 31 2005, 00:05:10)
Type "copyright", "credits" or "license" for more information.

In [1]: len(iter(()))
Out[1]: 0

In [2]: bool(iter(()))
Out[2]: False

And indeed, the built-in iterators have already backed away from this
idea.

Python 2.5c2 (r25c2:51859, Sep 13 2006, 09:50:32)
[GCC 4.1.2 20060814 (prerelease) (Debian 4.1.1-11)] on linux2
Type "help", "copyright", "credits" or "license" for more information.Traceback (most recent call last):
True


Carl Banks
 
A

Antoon Pardon

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

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.
I don't think of 10 > 5 as Something while 5 < 10 would be
Nothing. 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. 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.
 
A

Antoon Pardon

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.

The latter will treat None and False the same as [], () and {},
which in most of my code is not what I want. In most cases
I find testing for an empty sequence (however you do it)
useless, because the loop over the sequence does whatever
I want if it is empty. In cases where I do want to test
for it I usually write:

if len(my_list) > 0:

That provides the polymorphism that is usefull to me and
doesn't treat None the same as an empty sequence.
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.

I think you are incorrect. Decisions have to be made and
they are made based on conditions. Conditions are expressed
in terms of True and False not in terms of Nothing or Something.

That is how IMO people think. You can't change that just
because python is implemented with the Nothing vs Something
distinction in mind.
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.

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?
 
F

Fredrik Lundh

Antoon said:
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, what you do in your code is not very
interesting to anyone.

</F>
 
A

Antoon Pardon

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

Antoon Pardon

Antoon said:
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 {}
 
S

Steve Holden

Antoon said:
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
 
S

Steve Holden

Antoon said:
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
 
S

Steven D'Aprano

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

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

Steven D'Aprano

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

Donn Cave

Antoon Pardon said:
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, (e-mail address removed)
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top