True inconsistency in Python

A

Alex Martelli

Gerrit said:
Alex Martelli wrote:
(about x vs. bool(x))
[[ we TOLD Guido people would start on this absurd path, when
he added bool, True, and False, but he wouldn't listen...
]]

What do double square brackets mean?

"Inline footnote" or the like;-). I do like to pep up my posts
despite the limitations of plain ascii...

(btw, I _do_ use bool ocasionally: I implemented an anytrue() function
using sum([bool(i) for i in L]), is this wrong?)

Not wrong, just potentially a bit slow for very large L's, but for
your applications you may not care. Compare:


[alex@lancelot tmp]$ timeit.py -c -s'xs=[0]*999' -s'
def anytrue_sc(L):
for i in L:
if i: return True
else:
return False
def anytrue_ns(L):
return sum([ bool(i) for i in L ])
' 'anytrue_sc(xs)'
1000 loops, best of 3: 200 usec per loop

and the same with 'anytrue_ns(xs)' instead,

1000 loops, best of 3: 1.26e+03 usec per loop

while, also, with 'anytrue_sc([1]+xs]':

10000 loops, best of 3: 22 usec per loop

while with 'anytrue_ns([1]+xs]':

1000 loops, best of 3: 1.29e+03 usec per loop


So, on a 1000-long list, you may be slowing things down by 6 to
60 times, depending on where (if anywhere) the first true item
of L might be, by using the "clever" bool rather than the plain
good old loop-with-shortcircuit.

Now, for some people "one-liners" (which you could write the _ns
version as; the _sc version can't be less than 4 lines) are much
more important than speed or elementary-clarity. For those
people, I suggest an approach that's only a BIT slower than the
simplest and most obvious one:

[alex@lancelot tmp]$ timeit.py -c -s'xs=[0]*999' -s'import itertools as it
import operator
def anytrue_it(L):
return list(it.islice(it.dropwhile(operator.not_, L),1))
' 'anytrue_it(xs)'
1000 loops, best of 3: 310 usec per loop

and with 'anytrue_it([1]+xs)', 28 usec per loop. Now, you have
bounded your performance loss to 30-50% when compared to the simplest
approach, and one can of course pull out all the stops...:

[alex@lancelot tmp]$ timeit.py -c -s'xs=[0]*999' -s'import itertools as it
import operator
def anytrue_it(L, slice=it.islice, drop=it.dropwhile, not_=operator.not_):
return list(slice(drop(not_, L),1))
' 'anytrue_it(xs)'
1000 loops, best of 3: 270 usec per loop

to reach a 35%-or-so max loss of performance in this case.

Plus, it's much cooler for the purpose of making your friends' heads
spin with admiration for your wizardry, of course;-).


Alex
 
T

Tim Roberts

Scott Chapman said:
Historically Python has allowed <> 0 to equal true in evaluations. Now
<> 0 still evaluates to true in evaluations. However it doesn't equal
True. They are not interchangable. (Same with empty lists, etc.)

Python is certainly not the only language in which this occurs. Many are
the C programmers who have been burned by:

int SomeFunction();
...
if( SomeFunction == TRUE )
{
}

Visual Basic has exactly the same problem. Further, until very recently,
True in VB actually evaulated to -1, so even comparing to "1" would fail.

This should not be a surprise. Booleans should be thought of as enumerated
integral types.
Assuming the old behavior is desired, programmers need to be careful
not to compare a variable with True as in:

if var == True: # only works if var is 1
blah

Your statement is absolutely true. End of story.
 
E

Erik Max Francis

Tim said:
Python is certainly not the only language in which this occurs. Many
are
the C programmers who have been burned by:

int SomeFunction();
...
if( SomeFunction == TRUE )
{
}

I think you're getting burned by something else, there :).
Visual Basic has exactly the same problem.

It's not a problem, explicitly comparison with a Boolean literal,
whether or not Booleans are not distinct types (Lisp, C89), are distinct
types with implicit conversion (C++, Python), or are distinct types in
which implicit conversions are disallowed (Java) is completely
superfluous. The proper way to test whether an expression is true is

if (expression)
...

What is the point of the explicit test with the true constant? What
about the result of _that_ comparison, shouldn't that be tested with
true as well -- ((expression == TRUE) == TRUE)? But what about _that_
result, shouldn't it be tested too?

Explicit comparison with the true constant (or false constant)
necessarily degenerates into complete uselessness.
Further, until very
recently,
True in VB actually evaulated to -1, so even comparing to "1" would
fail.

That's because in traditional BASIC, "true" is all-bits on. The true
constant wasn't 1 in the first place.
Your statement is absolutely true. End of story.

It's true in that that might cause a problem, but it's not true that
that's undesirable language behavior. It's programmer error -- in any
language that has a Boolean true (or false) literal.

--
Erik Max Francis && (e-mail address removed) && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \
\__/ So little time, so little to do.
-- Oscar Levant
 
K

KefX

Explicit comparison with the true constant (or false constant)
necessarily degenerates into complete uselessness.

(For those just joining us, this statement was made about all languages, not
just Python.)

I'm not so sure about that. In most languages (including Python), 'false' is
guaranteed to be only one value (usually zero), therefore comparing against it
poses no problem. I assume you're saying that doing so isn't problematic in any
way, it's just pointless.

Well, actually, some coding standards suggest you always compare against false.
This is so the code is slightly more clear, and "!= false" avoids the pitfall
that "== true" has. The problem of course is that some unwitting maintenance
programmer may decide that "== true" os more clear than "!= false", not
realizing it is wrong...which is why all maintenance programmers should read
programming standards. :) We can't program in baby C just for them, after all,
but we shouldn't make things unnecessarily difficult for them either, but I
think we have bigger things to worry about if a maintenance programmer fails to
understand such a simple concept after being told about it.

Now of course any idiot C (or C++, or Java) programmer knows that these two are
equivalent:

if(blah != false)
do_blah();

if(blah)
do_blah();

But if whatever goes in "blah" is really long (and often it is), you very
quickly see what is being compared: it's a straight boolean comparison, whereas
with the second you have to look at the whole thing, find no comparison
operator, and go, "oh, there's no explicit comparison so it's obviously an
implicit straight boolean comparison". This is especially valuable in really
long 'if' statements, such as one might want for an inverse parser (don't worry
if you don't know what one is). The idea is if you compare against 'false' all
the time, you won't forget it when it would actually give the code more
clarity.

One standard which suggests this is the one Steve Maguire proposes in the book
Writing Solid Code. This is probably the best book on C coding guidelines that
I've ever read, despite it being written by a Microsoft programmer. ;) Although
much of it is specific to C, a lot of the concepts apply to other languages,
including Python.

However, comparing against a boolean is discouraged in Python (but your
argument wasn't about Python specifically), so I wouldn't do it in Python: when
in Rome, do as the Romans do. Although, as a last thought, it should be
relatively easy to make it so that True returns '1' in any comparison except
against 0. A class would be able to do this easily by overriding __cmp__:

def true_class(bool):
def __cmp__(self, other):
if other:
return 1
else:
return 0

True = true_class()

(of course this class definition would be tweaked to make it a singleton)
I'm assuming there's a good reason for not doing it this way (or in an
equivalent fashion), though...what else might we add to this discussion?

- Kef
 
D

Dennis Lee Bieber

Tim Roberts fed this fish to the penguins on Sunday 16 November 2003
23:58 pm:
Visual Basic has exactly the same problem. Further, until very
recently, True in VB actually evaulated to -1, so even comparing to
"1" would fail.

This should not be a surprise. Booleans should be thought of as
enumerated integral types.
Then there is VMS, in which odd return codes would evaluate to true
and even return codes to false (odd codes being "info"/"success", even
codes being "error"/"warning"). ie; 1, 3, 5, ... are "true"; 0, 2, 4
.... are "false".

--
 
R

Ron Adam

I think you're getting burned by something else, there :).


It's not a problem, explicitly comparison with a Boolean literal,
whether or not Booleans are not distinct types (Lisp, C89), are distinct
types with implicit conversion (C++, Python), or are distinct types in
which implicit conversions are disallowed (Java) is completely
superfluous. The proper way to test whether an expression is true is

if (expression)
...


To me the usefulness of using True and False is that it is defined to
values consistent with the programming language that you are using.
So using them to assign x = True, or x = False. insures that when I
do:

x = True
if x:
....

So I get consistent results for the language and platform I'm using
now and in the future. If down the road someone decided to make True
= 3, and False = -5, and they change the language so that any boolean
comparisons return 3 and -5 respectively, my use of True and False
will still work. If I tested for 1 or 0 using the 'if x:' method,
then my program will break.

x = 1
if x: # returned value undefined, x is not 3 or -5

So I do an explicit test 'if (x=1)' to make sure it will work even if
'True' gets redefined.

So we should either use explicit comparisons of values, or use only
True and False, but not mix them.

What is the point of the explicit test with the true constant? What
about the result of _that_ comparison, shouldn't that be tested with
true as well -- ((expression == TRUE) == TRUE)? But what about _that_
result, shouldn't it be tested too?

Explicit comparison with the true constant (or false constant)
necessarily degenerates into complete uselessness.


That's because in traditional BASIC, "true" is all-bits on. The true
constant wasn't 1 in the first place.


It's true in that that might cause a problem, but it's not true that
that's undesirable language behavior. It's programmer error -- in any
language that has a Boolean true (or false) literal.


It looks to me that 'True' in python is a combination of the boolean
binary logic of 1 or 0, and as an "exists" test of 0 or not 0.

If python had an exists operator, you could do.

if x exists:
'do something'

This could serve two options also... does the object exist? or does
a value exist where the value is not equal to zero or None. There
would need to be a syntax difference between the two.

Using the 'if x:' form does this for values and is clear enough. So
using an 'exists()' function to check for the presence of an object
would be useful if there isn't a simple way to do it already. Right
now it you do this without first assigning a value to x you get:
pass


Traceback (most recent call last):
File "<pyshell#2>", line 1, in -toplevel-
if x:
NameError: name 'x' is not defined
There is an os.path.exists() function for checking if a file path
exists. A more general exists() function or method my be useful and
still be consistent with it.

With pythons dynamic variables, I think an exists function would be
useful to check if an object exists. And to use 'if x:' to check if
a (value!=0) exists. It's clear what is being tested for from the
context.

I can't do:

def exists(object):
try object:
return True
return False

if not exists(object):
object = 0


This generates a not defined error if object isn't defined when exists
is called.


So I have to do:


try:
if object:
exist = True
except:
exist = False
if not exist:
object = 0

That can be shortened to:

try:
if object:
pass
except:
object = 0

This isn't to bad, but I would prefer something like,

if not object.exists: # does the abject already exist?
object = 0 # if not, create and set initial value
# else use the existing value

I think I diverged from True or False a bit here. And I'm not sure if
this functionality already exists or not?

_Ron Adam



























There's probably a way to do this in python already.
 
M

Michael Geary

KefX:
Well, actually, some coding standards suggest you always compare against false.
This is so the code is slightly more clear, and "!= false" avoids the pitfall
that "== true" has. The problem of course is that some unwitting maintenance
programmer may decide that "== true" os more clear than "!= false", not
realizing it is wrong...which is why all maintenance programmers should read
programming standards. :) We can't program in baby C just for them, after all,
but we shouldn't make things unnecessarily difficult for them either, but I
think we have bigger things to worry about if a maintenance programmer fails to
understand such a simple concept after being told about it.

Now of course any idiot C (or C++, or Java) programmer knows that these two are
equivalent:

if(blah != false)
do_blah();

if(blah)
do_blah();

But if whatever goes in "blah" is really long (and often it is), you very
quickly see what is being compared: it's a straight boolean comparison, whereas
with the second you have to look at the whole thing, find no comparison
operator, and go, "oh, there's no explicit comparison so it's obviously an
implicit straight boolean comparison". This is especially valuable in really
long 'if' statements, such as one might want for an inverse parser (don't worry
if you don't know what one is). The idea is if you compare against 'false' all
the time, you won't forget it when it would actually give the code more
clarity.

That strikes me as a really bad practice, in C, Python, or any language with
a similar if statement. Code should read the way people think, and people
don't tack on "!= false" when they make decisions based on conditions.

Which would you say: "If you're hungry, eat!" or "If your hunger is not
equal to false, eat!"

So which is more clear:

if( hungry )
eat();

or:

if( hungry != false )
eat();

It's just as bad when you want to make the opposite test. Do you say, "If
you're not hungry, don't eat!" or "If your hunger is equal to false, don't
eat!"

So do you code:

if( ! hungry )
dontEat();

or:

if( hungry == false )
dontEat();

(For those not familiar with C, "!" is the logical not operator and is
pronounced "not".)

I don't buy the argument that "you have to look at the whole thing, find no
comparison operator, and go, 'oh, there's no explicit comparison so it's
obviously an implicit straight boolean comparison.'" You *always* have to
look at the whole thing, and an if statement always tests its entire
argument for truth or falsity. Adding an explicit "!= false" or "== false"
simply adds noise and reduces clarity.

Comparing against a boolean isn't discouraged in Python because of some
arbitrary cultural preference, it's discouraged because it makes code harder
to read and understand.

-Mike
 
E

Erik Max Francis

KefX said:
I'm not so sure about that. In most languages (including Python),
'false' is
guaranteed to be only one value (usually zero), therefore comparing
against it
poses no problem. I assume you're saying that doing so isn't
problematic in any
way, it's just pointless.

Yes. The same cascade into insanity developes. If you're testing for
falsity, why not write x == false? But what about _that_ test,
shouldn't that be (x == false) != false? And _that_ test ...
Well, actually, some coding standards suggest you always compare
against false.

My point is that any such coding standard is dumb.
But if whatever goes in "blah" is really long (and often it is), you
very
quickly see what is being compared: it's a straight boolean
comparison, whereas
with the second you have to look at the whole thing, find no
comparison
operator, and go, "oh, there's no explicit comparison so it's
obviously an
implicit straight boolean comparison".

I don't see the value in this. The expression in an if statement is
treated as a Boolean expression. In languages where there isn't a
distinct Boolean type without implicit conversions (like your example,
C89), it doesn't matter whether you put the explicit comparison there or
not. However long the expression is, I don't see how adding `== true'
at the end makes it more clear. It's a Boolean test, what's to make
explicit?

All including the explicit test there does is make other programmers
wonder if you've lost your mind, and admit the possibility of you making
the type of error we've been discussing (x == True) where True is a
solitary constant in a much larger world of Booleans which evaluate as
true. Trying to correct that error, you end up with monstrosities such
as bool(x) == True or operator.truth(x) == True (or the equivalent in
other languages), and after some point it should dawn on the programmer
that the explicit True test is pointless.

--
Erik Max Francis && (e-mail address removed) && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \
\__/ Why don't you grow up for crying out loud?
-- Capt. Benjamin "Hawkeye" Pierce
 
E

Erik Max Francis

Ron said:
To me the usefulness of using True and False is that it is defined to
values consistent with the programming language that you are using.

I agree, insofar as the value of True and False as constants is that now
have values set aside which mean _nothing_ but their Boolean values.
This is very helpful for writing self-documenting code, something which
I've always been a strong supporter of. If I have code where 0 or 1
gets assigned to a variable, I'm going to have to look at the whole
block to tell precisely what that's being used for: Is it a counter
variable, a three-state value (say, -1, 0, and +1), is it an enumerated
value type, or is it a Boolean? If I'm scanning code and I see

x = True

then I know right away that what I'm looking at is a variable used as a
Boolean. (Of course, in proper self-documenting code, the variable
would be named something more helpful than `x', but you see my point.)
So using them to assign x = True, or x = False. insures that when I
do:

x = True
if x:
....

So I get consistent results for the language and platform I'm using
now and in the future. If down the road someone decided to make True
= 3, and False = -5, and they change the language so that any boolean
comparisons return 3 and -5 respectively, my use of True and False
will still work. If I tested for 1 or 0 using the 'if x:' method,
then my program will break.

While this may be true in some sense, I don't think this is a powerful
argument for using True/False. The chances of this happening are
utterly remote, since it would break practically all code. (Obviously
you weren't suggesting it was a real possibility given your choices of
the alternate constants, but still.)

I don't consider insulation from something utterly implausible happening
very persuasive, since I'm not worried about that utterly implausible
thing happening. I find explicit Boolean constants available for
writing self-documenting code much more compelling.

--
Erik Max Francis && (e-mail address removed) && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \
\__/ Why don't you grow up for crying out loud?
-- Capt. Benjamin "Hawkeye" Pierce
 
R

Ron Adam

I agree, insofar as the value of True and False as constants is that now
have values set aside which mean _nothing_ but their Boolean values.
This is very helpful for writing self-documenting code, something which
I've always been a strong supporter of. If I have code where 0 or 1
gets assigned to a variable, I'm going to have to look at the whole
block to tell precisely what that's being used for: Is it a counter
variable, a three-state value (say, -1, 0, and +1), is it an enumerated
value type, or is it a Boolean? If I'm scanning code and I see

x = True

then I know right away that what I'm looking at is a variable used as a
Boolean. (Of course, in proper self-documenting code, the variable
would be named something more helpful than `x', but you see my point.)


While this may be true in some sense, I don't think this is a powerful
argument for using True/False. The chances of this happening are
utterly remote, since it would break practically all code. (Obviously
you weren't suggesting it was a real possibility given your choices of
the alternate constants, but still.)

No, this one point is not the only reason, I made the example a
little farfetched to demonstrate a concept I think is a valid reason
to have 'True' and 'False' as Constants. Their actual internal
values shouldn't be relevant or depended on. They need to be constant
to how a boolean expression evaluates in the language they are in.

In python you can change the value of True, or set True to point to
something different.

For example you can do this.
False

Now all bets are off.... To be sure that True is True and False is
False, we need to put in explicit definitions into our programs.
True


True should be a Constant and always equal to (1==1) and False should
always be equal to (1!=1). It's not, so we need to be careful
using True.

x = True

"lots of code"

True = 3 # as a programming error.

"more code"

if (x == True): # evaluates as False!
print True
else:
print False


or possibly this.....


True = 0 # another programming error

"lost of code"

x = True
if x: # evaluates as False again!
print True
else:
print False

I don't consider insulation from something utterly implausible happening
very persuasive, since I'm not worried about that utterly implausible
thing happening. I find explicit Boolean constants available for
writing self-documenting code much more compelling.

The above is much less implausible. Do you agree?


_Ronald Adam
 
E

Erik Max Francis

Ron said:
No, this one point is not the only reason, I made the example a
little farfetched to demonstrate a concept I think is a valid reason
to have 'True' and 'False' as Constants. Their actual internal
values shouldn't be relevant or depended on. They need to be constant
to how a boolean expression evaluates in the language they are in.

In effect you are arguing against the point you were trumpeting earlier.
If we take your argument to its logical conclusion, that means that True
and False may be modified (accidentally or intentionally) by a
programmer and so we should never rely on its value. Which means that
you should never use True or False.

Of course, the fact that any builtin can be overridden sort of dulls
that point, since that means you shouldn't use _anything_.
In python you can change the value of True, or set True to point to
something different.

For example you can do this.

False

Now all bets are off....

Sure, but that's got nothing to do with True or False as specific
entities. This can happen with any builtin function, even the
type/converters:

Since these can happen with any of these things, singling out True and
False doesn't make sense.
True should be a Constant and always equal to (1==1) and False should
always be equal to (1!=1). It's not, so we need to be careful
using True.

I really don't see your point here. It's true that someone malicious or
insufficiently careful can override the values of "constants" like True
or False. Of course that's true with all the other builtin functions,
constants, and types, so that point really has nothing to do with True
or False.

So how does this point relate to explicit testing against the values of
True or False
The above is much less implausible. Do you agree?

Yes, but it is still programmer error. If `str' got overridden -- quite
frankly, a much more common programmer error -- you'd have the same
problem, and it has nothing to do with Booleans.

--
Erik Max Francis && (e-mail address removed) && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \
\__/ And there inside our private war / I died the night before
-- Sade
 
K

KefX

Yes. The same cascade into insanity developes. If you're testing for
falsity, why not write x == false? But what about _that_ test,
shouldn't that be (x == false) != false? And _that_ test ...

Of course the point that those tests aren't any less redundant from the
language perspective is valid. But they're a heck of a lot more redundant to a
human reader than a single "== false".
My point is that any such coding standard is dumb.

In my experience, every coding standard has things one would call "dumb". But
not everybody calls the same thing dumb. (I remember some people objecting to
my assertion that "assert" should be used as often to check parameters in C
code when defining functions...I still don't get how that's dumb. Some even
claimed that assert was a C++ thing!)
I don't see the value in this. The expression in an if statement is
treated as a Boolean expression. In languages where there isn't a
distinct Boolean type without implicit conversions (like your example,
C89), it doesn't matter whether you put the explicit comparison there or
not. However long the expression is, I don't see how adding `== true'
at the end makes it more clear.

What if the expression is 37 lines long? (Can't happen? I'm LOOKING at such an
example!) Fishing out the main comparison in such a monster isn't always the
easiest thing to do. Of course I'm exaggerating here, since we usually don't
write 37-line expressions, but still.
It's a Boolean test, what's to make
explicit?

Yes, all tests are boolean tests in the sense that they evaluate to a bool and
the if statement then compares the result, but not all comparisons are boolean
comparisons in the sense that we don't always compare to a boolean value. In
other words, "a == 0" isn't comparing against true or false, it's comparing
against an integer. It's worth noting here that omitting the "== 0" here is
considered bad style by many (though this is by no means universal). The camp
that would have you write "== false" invariably falls in the same camp that
would have you write "== 0", because that way the two would be consistent in
that you always specify what's being compared to what. Of course, this doesn't
mean everybody would have you write "== 0" would also have you write "==
false". The idea is consistency (I don't know how that slipped my mind in my
original posting.)
All including the explicit test there does is make other programmers
wonder if you've lost your mind

Not all programmers would think that, again. :)
Trying to correct that error, you end up with monstrosities such
as bool(x) == True or operator.truth(x) == True (or the equivalent in
other languages), and after some point it should dawn on the programmer
that the explicit True test is pointless.

I don't see how that would logically follow just from making an explicit bool
test. We know that such code is broken when we consider it, and then we reject
it, and we just do it the way we always did it, whether that's omitting the
explicit comparison altogether or comparing against false, or whatever other
possibility.

- Kef
 
R

Ron Adam

In effect you are arguing against the point you were trumpeting earlier.
If we take your argument to its logical conclusion, that means that True
and False may be modified (accidentally or intentionally) by a
programmer and so we should never rely on its value. Which means that
you should never use True or False.

I'm not arguing at all. Only exploring the issue.

I don't know if we should never use True and False. It's as
dependable as any other variables and we need to handle them in the
same way. That includes making sure they have not been changed if we
use them for something that can be a mission critical application.
ie...

True = (1==1)
False = (1!=1)

or if you prefer;

True = bool(1)
False = bool(0)

The interpreter initializes True and False when it starts. So for
small applications, they are fairly dependable, it shouldn't be a
problem to use them. For large application with multiple files
imported into them written by several programmers, it might not be a
bad idea to initialize them like above to be safe.

This of course is why they are constants in other languages. It
increases the dependability of the code. Both by using True and False
and by making sure they cannot be changed.
Of course, the fact that any builtin can be overridden sort of dulls
that point, since that means you shouldn't use _anything_.

It may be beneficial to make changes to built in's not so easy in some
cases.
return 32

Traceback (most recent call last):
File "<pyshell#4>", line 1, in -toplevel-
int(2.3)
TypeError: int() takes no arguments (1 given)

So maybe you are correct, we shouldn't use anything. (?)

Being able to change things in Python is one of the reasons that makes
it powerful, but being able to depend on certain things being
consistent is also a good thing. So where do these intersect? What
is the optimum mix of the two?

Sure, but that's got nothing to do with True or False as specific
entities. This can happen with any builtin function, even the
type/converters:

Yes, so what are True and False? Are they just preinitialized
variables? Are do they have special properties of their own?

From what I've seen so far, the 'True' and 'False' values are useful,
but the names 'True' and 'False' can be changed and aren't synonymous
with the values 'True' and 'False'. Two different things.

So how would you use True and False? I say go ahead and use them to
make your code readable, but if its a large or mission critical
application, you might want to make sure they are what they should be
before you do by initializing them the same as you would any other
variable.

Since these can happen with any of these things, singling out True and
False doesn't make sense.


I really don't see your point here. It's true that someone malicious or
insufficiently careful can override the values of "constants" like True
or False. Of course that's true with all the other builtin functions,
constants, and types, so that point really has nothing to do with True
or False.

If a programmer is malicious and wants to sabotage code, making True
and False constants will hardly stop them.
So how does this point relate to explicit testing against the values of
True or False

Well if True and False can be changed, then it really isn't an
explicit test is it? It's a relative test.

if you want to test if a value is explicitly equal to 'True', you
need to use (value == (1==1)).

And if you want to explicitly test if something is equal to 'false',
use (value ==(1!=1)).

These will always work. And doing:

if x: # x is not 'False'

is not the same as:

if x=True:

This is because Bools are a subset of ints and not a subset of binary
as in some other languages. If they were a subset of binary, they
would be equivalent. We just need to be aware of that. Bools as a
subset of ints give the advantage of 'if x:'. where x is true if its
not 0 instead of x only being "True" if it's equal to 1.

I'm probably repeating what's already been said in this thread
already.

Yes, but it is still programmer error. If `str' got overridden -- quite
frankly, a much more common programmer error -- you'd have the same
problem, and it has nothing to do with Booleans.

What am I missing? The thread is about 'True inconsistency in
Python', and the reason it's inconsistent is because it can be changed
so easy.

Doing this causes an error:
SyntaxError: can't assign to literal


Doing this does not cause an error:

Are True and False Bools?

Why are they not also literals? Wouldn't that be consistent?


_Ronald Adam
 
B

Ben Finney

un-attributed author said:
I don't see the value in this. The expression in an if statement is
treated as a Boolean expression. [...]
However long the expression is, I don't see how adding `== true' at
the end makes it more clear.

What if the expression is 37 lines long?

What of it? Is a long expression in an 'if' statement somehow less
likely to be treated as Boolean? What does appending ' == True' gain?
How could it not be obvious that the entire expression will be evaluated
for Boolean truth, when the expression is the argument to 'if' ?
Fishing out the main comparison in such a monster isn't always the
easiest thing to do.

How does "fishing out the main comparison" have anything to do with
appending ' == True' to the expression?
"a == 0" isn't comparing against true or false, it's comparing against
an integer.

Correct. The comparison, though, is a Boolean expression, which will
evaluate to either True or False. Its use in an 'if' statement will
always evaluate it this way.
It's worth noting here that omitting the "== 0" here is
considered bad style by many (though this is by no means universal).

Only in cases where ' == 0' is *not* a test for Boolean falsity.
Compare a variable against 0 if you want to test if its value is
numerically zero; evaluate the variable if it is supposed to contain a
Boolean true or false value.
The camp that would have you write "== false" invariably falls in the
same camp that would have you write "== 0", because that way the two
would be consistent in that you always specify what's being compared
to what.

No. The argument to 'if' is a Boolean expression. A test against
numeric zero is not the same as a test against Boolean false, except by
implementation coincidence.

If the variable 'a' is conceptually containing a numeric value, then
using it as a Boolean value implies things that are not necessarily true
about the Boolean implementation. Hence, 'if( a == 0 )' and not
'if( ( a == 0 ) == True )'. Similarly, testing the negative case is
'if( not ( a == 0 ) )'. No explicit comparison to True or False is
required.

If the variable 'a' is conceptually containing a Boolean value, then
using it as the argument to 'if' is consistent. Hence, 'if( a )' and
not 'if( a == True )'. Similarly, testing the negative case is
'if( not a )'. No explicit comparison to True or False is required.

Once the expression *reads as a Boolean expression*, then adding further
comparisons against Boolean values helps nothing.
The idea is consistency (I don't know how that slipped my mind in my
original posting.)

I, too, value consistency, which is why I abhor adding ' == True' to
some Boolean expressions but not to others. It should be added to none
of them.

You appear to want semantic consistency between types (integer and
Boolean) that *by design* aren't semantically consistent. The 'if'
statement takes a Boolean expression as argument; to be consistent, one
passes it a Boolean expression argument, not some other type of
argument.
 
E

Erik Max Francis

KefX said:
What if the expression is 37 lines long? (Can't happen? I'm LOOKING at
such an
example!) Fishing out the main comparison in such a monster isn't
always the
easiest thing to do. Of course I'm exaggerating here, since we usually
don't
write 37-line expressions, but still.

What if it's twenty pages long? I still don't see the benefit. If
you're looking at an expression in an if statement, you need to look at
the _whole_ expression to figure out what it's doing. I don't see how
ending it with `== True' makes it any more readable.
Yes, all tests are boolean tests in the sense that they evaluate to a
bool and
the if statement then compares the result, but not all comparisons are
boolean
comparisons in the sense that we don't always compare to a boolean
value. In
other words, "a == 0" isn't comparing against true or false, it's
comparing
against an integer. It's worth noting here that omitting the "== 0"
here is
considered bad style by many (though this is by no means universal).

Well, if you leave off the `== 0', it means something else.
The camp
that would have you write "== false" invariably falls in the same camp
that
would have you write "== 0", because that way the two would be
consistent in
that you always specify what's being compared to what.

Not even a little. An explicit test for an individual value is one
thing. An explicit comparison for an individual value _when there are
only two possible categories_ (true or false) is utterly pointless,
because all it does is add the opportunity to create an error.
Of course, this
doesn't
mean everybody would have you write "== 0" would also have you write
"==
false". The idea is consistency (I don't know how that slipped my mind
in my
original posting.)

It's not at all consistent, that's the problem. Not to mention the
fact, as others pointed out, that not all false values are False.
I don't see how that would logically follow just from making an
explicit bool
test.

Because in Python the explicit Boolean test cannot possibly be anything
other than redundant. If it is not redundant, it is probably an error.

--
Erik Max Francis && (e-mail address removed) && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \
\__/ So little time, so little to do.
-- Oscar Levant
 
E

Erik Max Francis

Ron said:
I'm not arguing at all. Only exploring the issue.

Maybe you should summarize your central tenets, I'm afraid they've
gotten lost. It seems like we've run around in a big circle.
The interpreter initializes True and False when it starts. So for
small applications, they are fairly dependable, it shouldn't be a
problem to use them. For large application with multiple files
imported into them written by several programmers, it might not be a
bad idea to initialize them like above to be safe.

Unless you're using naughty things like `from module import *', no
collision can occur. If you are, why are you more worried about
collisions with the True/False constants, rather than any of the other
builtins? They're all just as possible.
So maybe you are correct, we shouldn't use anything. (?)

My point is that you need to expect a sane environment. If you're
working with fellow engineers who keep planting time bombs, maybe they
should be removed from the team rather than having to defensively work
around their potential disasters.

Python has as a central concept that everyone's an adult. If you want
to mess things up really badly, you can. If you want to use some clever
trick in order to save a lot of work, you can do that too. With power
and flexibility comes the ability to mess things up really badly. Lack
of constants is an example of this idea in Python (as is, for example,
the lack of access control on object attributes).

If someone's going to keep overriding True and False, or int, or open,
then you're not going to get anywhere. Python isn't designed so that
you can write code that is completely protected from the misbehavior of
other engineers. And it shouldn't be.
Yes, so what are True and False? Are they just preinitialized
variables? Are do they have special properties of their own?

They're builtins, just like all the other builtins like int, max, file,
map, etc.
From what I've seen so far, the 'True' and 'False' values are useful,
but the names 'True' and 'False' can be changed and aren't synonymous
with the values 'True' and 'False'. Two different things.

All the other "preinitialized variables" have exactly the same
characteristic. There are no constants in Python.
So how would you use True and False? I say go ahead and use them to
make your code readable, but if its a large or mission critical
application, you might want to make sure they are what they should be
before you do by initializing them the same as you would any other
variable.

I never suggested that True and False shouldn't be used; far from it. I
just used your objection (that their values can be overridden) to
illustrate a reductio ad absurdum. Either that's a really scary thing
(which you can't defend against) and the interpreter comes crumbling
down, or you assume that people are going to behave themselves and don't
worry about it.
If a programmer is malicious and wants to sabotage code, making True
and False constants will hardly stop them.

Exactly. So I don't understand what your point is; you're the one who
brought up the danger of overriding True and False.
What am I missing? The thread is about 'True inconsistency in
Python', and the reason it's inconsistent is because it can be changed
so easy.

You've gotten severely sidetracked on this thread. The original
inconsistency mentioned in this thread is that explicit comparisons with
True or False do not involve an implicit conversion to bool. So 3 ==
True is False, even though bool(3) == True is True.
Doing this causes an error:

SyntaxError: can't assign to literal

Doing this does not cause an error:

That's because a literal is not a name that can be assigned to, anymore
than

'asdf' = 2 + 3

could possibly make any sense. True and False are, on the other hand,
names.
Are True and False Bools?

True and False are names which are initially bound to the true and false
Boolean values, respectively. They're names like any other names: x,
thisIsAVariable, int, str, sys, etc.
Why are they not also literals? Wouldn't that be consistent?

They're not literals because that's not the way that they're handled by
the language. None, for instance, is not a literal; it's a name. So
neither are True and False.

--
Erik Max Francis && (e-mail address removed) && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \
\__/ So little time, so little to do.
-- Oscar Levant
 
T

Terry Reedy

Ron Adam said:
x = True
if x:
....

since the above snippert is equivalent to

if True:
....

which is equivalent to

....

you must have meant something more imvolved. But I am having trouble
filling in the missing pieces.
So I get consistent results for the language and platform I'm using
now and in the future. If down the road someone decided to make True
= 3, and False = -5, and they change the language so that any boolean
comparisons return 3 and -5 respectively, my use of True and False
will still work.

This strikes me as comparable to worrying about being killed by an
asteroid. Is there some actual historical event that makes it more
plausible to you?

'Someone' would have to be someone with the authority to make such a
change in either the language or a particular implementation thereof.
Such people are usually at least somewhat sane. If someone did make
such a lunatic change, I suspect that it would not be the only one,
and one would have to be a lunatic to keep using that
language/implementation for serious work. Unless the language were
locked up and proprietary, users could reject such a change anyway.
(On the other hand, exposure to lesser lunacies *is* one of the risks
of using proprietary unclonible systems.)

....
It looks to me that 'True' in python is a combination of the boolean
binary logic of 1 or 0, and as an "exists" test of 0 or not 0.

I do not understand this. If you have a reference to 0, then 0
exists. If you do not, then the 'existence' or not of an int with
value 0 is irrelevant.
If python had an exists operator, you could do.

I think you are confusing names and objects. You can only apply an
operator to objects and only to objects that exist.
if x exists:
'do something'

Do you mean
if bound_to_something('x'): <do something>
?

Normally, in the absence of error, one only uses names that one has
defined (bound to somethingj). So you must be worried about the
following scenario:

if a: x=1
<more code>
if exists(x): <do something with x>

In non-module script only:
import __main__ as mm
x = 1
hasattr(mm, 'x') # True
hasattr(mm, 'y') # False

Anywhere: use try ... except NameError

Or, don't do that (have conditionally defined name). Instead,

x=None
if a: x = something_not_None()
<more code>
if x != None: <do something with x>

In other words, name != None is often idiom for exists('name')!
This could serve two options also... does the object exist?

Again, Python only operates on objects that do exist.

....
With pythons dynamic variables, I think an exists function would be
useful to check if an object exists.

Same comment.

Terry J. Reedy
 
T

Terry Reedy

Ron Adam said:
No, this one point is not the only reason, I made the example a
little farfetched to demonstrate a concept I think is a valid reason
to have 'True' and 'False' as Constants.

The developers agree and would make them so now if it were not for
backward compatibility needs. They probably will make them so in the
future. Currently, reassigning None can get you a Warning.
Their actual internal
values shouldn't be relevant or depended on.

When the bool type was added, a few people argued for a pure bool type
with no relation to anything else. However, in Python, 'practicality
beats purity'. Having True/False == 1/0 now and forever has practical
uses.
In python you can change the value of True, or set True to point to
something different.

Yes, you are currently allowed to stab yourself in the back (but even
this will probably change in the future). Don't do it.
For example you can do this.
Now all bets are off....
Ditto.

To be sure that True is True and False is
False, we need to put in explicit definitions into our programs.

In 2.2.2+, you only need to not change them and to not work with a
psycopath.

....
The above is much less implausible. Do you agree?

Yes, it is more plausible that you shoot yourself in the feet than
that Guido and the whole Python development community go bonkers. I
strongly suspect that PyChecker can check for assignments to True and
False (along with about a hundred other things). Get it and use it.

Terry J. Reedy
 
R

Ron Adam

since the above snippert is equivalent to

if True:
...

which is equivalent to

...

you must have meant something more imvolved. But I am having trouble
filling in the missing pieces.

Yes, the paragraph (that you snipped) above this code snippit,
explained that you need to be able to depend on 'True' being
consistent with how the underlying operating system evaluates boolean
expressions. If that trust is broken, then comparisons using True
may not work. Including "if True:".

This is so basic and simple, that you take it for granted. And so do
many others.

I believe the words 'True' and 'False' need to be treated the same as
the digits 1, 2, 3, ... The values of the digits do not change. We
depend on them not changing.

True should always evaluate to True also. So we can depend on it as
well.

This is my opinion, you don't have to agree with it.

This strikes me as comparable to worrying about being killed by an
asteroid. Is there some actual historical event that makes it more
plausible to you?

Again, it was an example of a concept. I was trying to point out
even if the underlying values that the operating system uses to
represent true and false are changed, having True as a constant equal
to a boolean true evaluation, will still work. I chose numbers that
are very unlikely to try demonstrate in an obvious way that the
concept is valid. Sorry, if I lost you.

Does making 'True' and 'False' constants and/or literals have any draw
backs for you? I can only think of benefits and don't see any reason
for not doing it in this particular case. While I admit that any
knowledgable programmer can write good programs without these being
constants or literals, I also realize that python is becoming
popular as a teaching tool for entry level programming. So yes, I
believe errors using and miss using True and False will happen.

...

I do not understand this. If you have a reference to 0, then 0
exists. If you do not, then the 'existence' or not of an int with
value 0 is irrelevant.

if x: is a test to see if the value 0 does not exist in x.

Or as someone has stated to me earlier... it is a test that something
does exist. That something being whatever the value x represents.

x is the number of coins I have. ' if x:' is a true statement if I
have some coins. We are testing for the existence of my coins.

I think you are confusing names and objects. You can only apply an
operator to objects and only to objects that exist.

No, I'm not confused, and yes I am diverging here.
Do you mean
if bound_to_something('x'): <do something>
?

Yes, you understand.
Normally, in the absence of error, one only uses names that one has
defined (bound to somethingj). So you must be worried about the
following scenario:

if a: x=1
<more code>
if exists(x): <do something with x>

In non-module script only:
import __main__ as mm
x = 1
hasattr(mm, 'x') # True
hasattr(mm, 'y') # False

Anywhere: use try ... except NameError

Or, don't do that (have conditionally defined name). Instead,

x=None
if a: x = something_not_None()
<more code>
if x != None: <do something with x>

In other words, name != None is often idiom for exists('name')!


Again, Python only operates on objects that do exist.

Yes, I noticed. The reason I bring this up is in situations where
you want to initialize a variable if it has not been defined yet, but
do not want to re initialize it if it's already been defined.

Being able to check if an object already exists could be useful. I'll
look into the hasattr() function more, thanks for pointing it out.

I did stray a bit on this and I admitted so in my post.


_Ronald Adam
 
B

Ben Finney

I believe the words 'True' and 'False' need to be treated the same as
the digits 1, 2, 3, ... The values of the digits do not change. We
depend on them not changing.

Possibly so. For myself, I think it's good that they exist at all now.
Incremental improvement toward a canonical Boolean type is good.

- We now have a separate 'bool' type.
- We now hove True and False singleton objects of type 'bool'.
- Boolean expressions now evaluate to one of these two objects.

These are all quite recent in Python. Perhaps immutable Boolean values
will be in a future Python version. However, I don't see that it's a
pressing need.

Assigning a new value to None is possible (until recently, it didn't
even generate a warning). How much Python code does this break? How
many potential errors does it cause? My guess would be few. Same for
the True and False values (and the numbers, if they were mutable).

There are many ways to shoot yourself in the foot in Python, if you try
hard enough. This is one of them. Acknowledge its existence,
acknowledge that you'd be crazy to do it, and move on.
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top