integer >= 1 == True and integer.0 == False is bad, bad, bad!!!

S

Steven D'Aprano

No because all integers should bool True. An integer is a value that IS
NOT empty

Integers aren't containers, the concept of "empty" or "full" doesn't
apply to them.
and IS NOT None.

By this definition, the string "rantingrick hasn't thought this through"
is an integer. It's not empty, and not None, so therefore an integer by
your definition.

Possibly the integer two-thirds of the way between 3 and 4.

Therefore the only logical way to handle
integer bool-ing is to say they are all True.

For some definition of "logical".

We would't deal with backwards compatibility as this notion of bool(1)
== True and bool(0) == False if backwards way of thinking. Sure it saves
a few keystrokes but in the end only serves to obfuscate the code and
promote bad programming styles. WE SHOULD NEVER BE USING 1 IN PLACE OF
True AND 0 IN PLACE OF False!

Nevertheless, what is done is done, and now you have to deal with it.
Just wishing that it was never done is not dealing with backwards
compatibility, and breaking existing code is not an acceptable option.

So if your plan is to refuse to deal with existing code, I am very glad
indeed that your plan will go absolutely nowhere.

I have considered this many times in the past and continue to
consider it even today.

Please do. I think that this will be the best thing for the Python
community.
 
R

rantingrick

Come back when you have profiled your code and
can prove that the cost of building empty tuples is an actual bottleneck.

Did you even read this thread, i mean from head to tail. I NEVER said
building EMPTY tuples was the cause of my rant. My complaint (an oddly
enough the title of this thread!) concerns the fact that Python treats
0 as False and every integer above and below 0 as True. Which is
another example of how *some* aspects of Python support bad coding
styles.

The only reason i used the tuple was so that my conditional logic
worked as expected.

*Stephen* offered a solution in the form of using tuples within the
conditional expression. I countered his solution by showing that
creating tuples in a conditional expression is slower that testing for
bool-inity.

*Steven*, Please read the thread completely before making off hand
comments else you could make a complete fool of yourself!
 
R

rantingrick

Integers aren't containers, the concept of "empty" or "full" doesn't
apply to them.

And again you failed to follow along with the thread so you have no
idea where my statements is projected from. Of course integers are NOT
containers in the way a list or dict is a container! My remark was a
rebuff of comments made by Stephen earlier.
By this definition, the string "rantingrick hasn't thought this through"
is an integer. It's not empty, and not None, so therefore an integer by
your definition.

Again you show lack of reading and comprehension skills. The fact that
an integer IS NOT None does not mean this is the only definition of an
integer. And any blabbing otherwise is just complete nonsensical crap.
If you think you're going to fly in here and dis-credit me that easily
you'd better pack a lunch next time! I gots my think'in cap on today
fella!
Nevertheless, what is done is done, and now you have to deal with it.
Just wishing that it was never done is not dealing with backwards
compatibility, and breaking existing code is not an acceptable option.

Yea and if Guido would have taking your defeatist attitude we'd all be
using braces for scope!

You know D'Aprano, i had once considered you one of the foremost
intelligent minds within this group. However, after your display
within this thread i am beginning to doubt my original beliefs of you.
Hopefully you're just having an "off" day?
 
S

Stephen Hansen

And again you failed to follow along with the thread so you have no
idea where my statements is projected from. Of course integers are NOT
containers in the way a list or dict is a container! My remark was a
rebuff of comments made by Stephen earlier.

I forgot to reply to that; an integer is certainly not empty.

But 0 is nothing.

Its not empty vs full. Its nothing vs something that determines if
something is considered true-ish or not.
Yea and if Guido would have taking your defeatist attitude we'd all be
using braces for scope!

Guido made a new language.

You should go do that.

Feel free to define it however you want.

In Python, the meaning of "truth" goes back a very, very, very long way.
It isn't going to change. Every once in awhile people hate it. For
awhile after True/False were introduced, some people wanted to go modify
things to a boolean strictness. But in the end, its all pointless.

This is just how it works. Its not going to change. It would break
thousands and thousands of lines of code. There's not going to be
another major breakage for, oh, maybe ten years. Or twenty. If ever.

--

Stephen Hansen
... Also: Ixokai
... Mail: me+list/python (AT) ixokai (DOT) io
... Blog: http://meh.ixokai.io/


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (Darwin)

iQEcBAEBAgAGBQJMOnDuAAoJEKcbwptVWx/lrTsH/RPUNTAPWt4aKXmOISlzPj3o
UeHfZ/HAVaGI22KNXULlHH1zQMyfPn9Bfz4nZuE9rlAp2naTUGXIB8sN0Hs2r5hh
Yvs5CnzLcVvKPbwqW9zLBdEGIpdZd9CK4VAo2csqpZycuvSQj290rlj5/TxqV2dj
PB0tRR7PoLBY9dM/o5ZAoCnplr54txLVf93jPQd4YLZXb2WR3Wb0Ngmrz+kFz5SE
yID5uxybkl5Xkl/DG9c9W4EGNjzTVq88umy3r6Lna1Jim7O0obgIAONusj5ySgIe
uj1lUpex05Mrre5WFPyfHIS7fzZtK2eJYnAZ/0Yu+rqG3uale+VA+DdKyo5Tq08=
=Xl6j
-----END PGP SIGNATURE-----
 
B

Brendon Wickham

"i had once considered you one of the foremost intelligent minds
within this group. However, after your display within this thread i am
beginning to doubt my original beliefs of you."

"Oh ... grow a spine already, really. I can't help but thinking of the
spineless Robert Ford every time you open your mouth"

@rantingrick : these comments among others fail to meet the standard
of engagement expected of, and traditional to, this list. Take a
breath, get some sleep and come back with a level head and a civil
tongue. If you have any valid point to make at all, your attitude so
far has failed to make it credible, and nor will it enable you to
enlist supporters.
 
S

Steven D'Aprano

Did you even read this thread, i mean from head to tail.

Yes I did.
I NEVER said
building EMPTY tuples was the cause of my rant.

The cause of your rant appears to be that you have nothing better to do
with your time. But the *excuse* for your rant was that you had to
replace:

choiceIdx1 = None

with:

choiceIdx1 = ()

and followed with:

Seems kinda dumb to build a tuple just so a conditional
wont blow chunks!

and

My bin packer could potentially compute millions of parts.
I do not want to waste valuable processor cycles building
numerous TUPLES just for the sake of a conditional
"condition"!

[emphasis added]

My complaint (an oddly
enough the title of this thread!) concerns the fact that Python treats 0
as False and every integer above and below 0 as True. Which is another
example of how *some* aspects of Python support bad coding styles.

Yes, Python does support bad coding styles. The treatment of 0 as a false
value is not one of them though.
 
J

Jean-Michel Pichavant

Steven said:
Yes, Python does support bad coding styles. The treatment of 0 as a false
value is not one of them though.

Well, actually some people might think otherwise. While I disagree with
the OP flaming style, one could argue that muting an integer into a
boolean makes no sense (I'm one of them). You can still do it, but there
is no "right" way to do it.
You can decide that everything else than 0 is True, but you could also
pickup the integer 3 as false value, it would work as well since it
makes no sense. This is just an arbitrary definition.
Where the OP is fooling himself, is that you can't state that bool-ing
an integer makes no sense and state the line after that 0 *should* |
*has to* return True.

I personally can live with 0 == False (with all due respect to our
C-coding ancestors :) ), however as one of my personal coding rule I
avoid using it.
I prefere to explicitly write what I want to test:

if myInt <> 0:

or

if myInt is not None:

etc...

That way I do not rely on a arbitrary int-to-bool mutation.

JM
 
S

Steven D'Aprano

Well, actually some people might think otherwise. While I disagree with
the OP flaming style, one could argue that muting an integer into a
boolean makes no sense (I'm one of them). You can still do it, but there
is no "right" way to do it.
You can decide that everything else than 0 is True, but you could also
pickup the integer 3 as false value, it would work as well since it
makes no sense. This is just an arbitrary definition.

Choosing 3 as a false value would be arbitrary, but the choice of 0 is
anything but arbitrary. The distinction that Python makes is between
values which are Something (true values) and those which are Nothing
(false values).

Python has an infinite number of ways of spelling Something:

True, 1, 2, 3.1415, "abc", (2, 4), [None, 1, "A"], ...

and a smaller number of ways of spelling Nothing:

False, None, 0, 0.0, "", (), [], ...

The fact that False == 0 (as opposed to, say, [] != 0) is due to the need
for backwards compatibility. That bools are implemented as a subclass of
int is a historical accident. The fundamental distinction in Python is
between objects which are Something and those that are Nothing, and
that's not an arbitrary distinction, it's a very deep distinction.

This is why virtually all low-level languages treat 0 as a false flag and
1 (or sometimes -1) as a true flag. I say "virtually all", not because I
know of any exceptions, but because in the history of computer languages
you can probably find every design mistake, arbitrary choice, and
perverse decision imaginable made by *somebody*.

Consider branch statements. Forth jumps to the "true" branch on any
integer flag, and to the "false" branch on 0, but the canonical true
value is either 1 (0000 00001 in binary) or -1 (1111 1111). Early
versions of BASIC used -1 as true and 0 as false.

With Pascal's strong type-checking, you were forced to use the boolean
type in branches, but (if I recall correctly) the language guaranteed
that false was 0 and true was 1: a packed array of bools would use a 0
bit for false and 1 for true, and an unpacked array would use eight zero
bits versus seven zeroes and an one.

So there's historical precedent from other languages, backwards
compatibility with early Python versions, and a fundamental philosophical
distinction all in favour of using 0 for false. Not arbitrary at all.

I prefere to explicitly write what I want to test:

if myInt <> 0:

I would argue against that. Why do you, the coder, care about the
specific details of treating ints in a boolean context? The int type
itself knows, leave the decision to it.

Sure, in the specific case of ints, the distinction is so fundamental, so
basic, and so unlikely to change, that there's no real harm in the
explicit test. But consider some other type:


if myValue.count <= 0 and myValue.next is None and myValue.blob == "":
# myValue is considered false

versus:

if not myValue:


Which would you prefer? I think the choice is obvious: the type knows
whether it is equivalent to true or false, leave it up to the object to
decide. Why bother making an exception for ints, or strings?
 
P

Paul Rubin

Steven D'Aprano said:
This is why virtually all low-level languages treat 0 as a false ...

OK, but is Python a low-level language, and if not, why are low-level
languages appropriate examples to follow?
I would argue against that. Why do you, the coder, care about the
specific details of treating ints in a boolean context? The int type
itself knows, leave the decision to it.

There is a horrible (IMO) thing that Perl, Lua, and Javascript all do,
which is automatically convert strings to numbers, so "12"+3 = 15.
Python has the good sense to throw a type error if you attempt such an
addition, but it goes and converts various types to bool automatically,
which is more Perl-like than I really enjoy. In fact Python 3 added yet
another automatic conversion, of int to float on division, so 1/2 = 0.5.

Obviously it's a point in the design space where various decisions are
possible, but I can get behind the "explicit is better than implicit"
idea and say that none of those conversions should be automatic, and if
1/2 = 0 was confusing people in Python 2 enough to justify changing
divison semantics in Python 3, the preferable change would be for int
division to raise TypeError rather than quietly converting to float.

The same thing goes for bool conversion, though we are all used to it by
now, and it would be way too disruptive a change.
if myValue.count <= 0 and myValue.next is None and myValue.blob == "":
# myValue is considered false
versus:
if not myValue:
Which would you prefer?

I'd personally prefer

if not bool(myValue):

which would call the myValue's __bool__ method if it chose to implement
one. Explicit is better than implicit.
 
I

Ian Kelly

I would argue against that. Why do you, the coder, care about the
specific details of treating ints in a boolean context? The int type
itself knows, leave the decision to it.

I think you're missing the point. He's not using ints in a boolean
context. If it were a boolean context, he would be using bools in the
first place. What he is objecting to is the practice of testing for
special cases of ints (i.e. 0) by treating them as bools. The
specific details of converting ints to bools are very much relevant
here; as long as 0 is false, it works. If -1 is false (a semantic I
have actually seen used), then it does not.

Cheers,
Ian
 
I

Ian Kelly

There is a horrible (IMO) thing that Perl, Lua, and Javascript all do,
which is automatically convert strings to numbers, so "12"+3 = 15.
Python has the good sense to throw a type error if you attempt such an
addition, but it goes and converts various types to bool automatically,
which is more Perl-like than I really enjoy.  In fact Python 3 added yet
another automatic conversion, of int to float on division, so 1/2 = 0.5..

Obviously it's a point in the design space where various decisions are
possible, but I can get behind the "explicit is better than implicit"
idea and say that none of those conversions should be automatic, and if
1/2 = 0 was confusing people in Python 2 enough to justify changing
divison semantics in Python 3, the preferable change would be for int
division to raise TypeError rather than quietly converting to float.

I don't think it's any more egregious than automatic conversions of
mixed-type expressions, such as 3 + 4.5. If you don't want your ints
automatically converted to floats on division, then use the integer
division operator. 1 // 2 is still 0 in Python 3.

Cheers,
Ian
 
P

Paul Rubin

Ian Kelly said:
I don't think it's any more egregious than automatic conversions of
mixed-type expressions, such as 3 + 4.5.

That could also be explicit: float(3) + 4.5, or 3 + int(4.5).
If you don't want your ints automatically converted to floats on
division, then use the integer division operator. 1 // 2 is still 0
in Python 3.

Sure, I do that, but the issue was that 1/2 was confusing newbies who
don't understand the different characteristics of int and floating
types. If the idea is to change Python to fix this problem in a
newbie-friendly way, the right fix is to create enlightment by raising
an exception that points out the problem, not sweep it under the rug
with an automatic conversion.
 
C

Cameron Simpson

| > This is why virtually all low-level languages treat 0 as a false ...
|
| OK, but is Python a low-level language,

Not particularly, but true/false and Boolean login are low level ideas.
If it works well in a low level language (where all you might have are
ints of various flavours and thus some equivalence notion is required),
why would you _change_ the conventions in a high level language without
a compelling reason? The more commonality in concepts there are, for
all that they are just conventions, the easier it is remember how to
do things.

| and if not, why are low-level
| languages appropriate examples to follow?

They may not be in any inherent sense, but they are examples and if the
usage doesn't cause pain are they inappropriate?

Steven:
| >> if myInt <> 0:
| >
| > I would argue against that. Why do you, the coder, care about the
| > specific details of treating ints in a boolean context? The int type
| > itself knows, leave the decision to it.
[...snip...]

This I'm only halfway with. I, the coder, _must_ know. The "if"
statement has an intent, and I need to know that "if myInt:" matches my
intent. Of course, using the right idioms it will match a lot of the
time. But I've certainly been bitten by writing:

if myDict:

intending:

if myDict is not None:

but also getting:

if myDict != {}:

Clearly the fault was mine, but I, the coder, _must_ care about the
details of using non-Booleans in a Boolean context.

Cheers,
--
Cameron Simpson <[email protected]> DoD#743
http://www.cskk.ezoshosting.com/cs/

It is Texas law that when two trains meet each other at a railroad crossing,
each shall come to a full stop, and neither shall proceed until the other has
gone.
 
S

Steven D'Aprano

I think you're missing the point. He's not using ints in a boolean
context. If it were a boolean context, he would be using bools in the
first place.

Of course he is -- he's branching on an int (a boolean context), and
explicitly writing out the test as myInt <> 0. In fact, that test could
just as easily be written as bool(myInt), which has the benefit of being
even more explicit that you want a bool.

It's also silly. Explicitness is not always a virtue. Beginners sometimes
write things like:

s = "hello "
t = "world"
print str(s + t)

and we rightly shake our heads at the sheer n00b-ness of it. Writing the
explicit tests:

if bool(myInt):

or even:

if myInt <> 0:

are firmly in the same category. The only difference is that it is more
familiar and therefore comfortable to those who are used to languages
that don't have Python's truth-testing rules.


What he is objecting to is the practice of testing for
special cases of ints (i.e. 0) by treating them as bools. The specific
details of converting ints to bools are very much relevant here; as long
as 0 is false, it works. If -1 is false (a semantic I have actually
seen used), then it does not.

You've seen -1 being used as false? Where? Are you still talking about
Python builtins or language semantics?

If you're about to say string.find(substring), no, absolutely not. find
does not return a true/false flag, it returns an index, with -1 the
sentinel for Not Found. This is not a flag!

In fact, one of the motivations for adding bools to Python was to avoid
people mistakenly thinking that cmp(a, b) returned a flag 0, 1 when it
actually returns a three-state -1, 0, 1. This was a common source of
errors before Python got bools.
 
P

Paul Rubin

Steven D'Aprano said:
Writing the explicit tests:
if bool(myInt):
or even:
if myInt <> 0:

are firmly in the same category. The only difference is that it is more
familiar and therefore comfortable to those who are used to languages
that don't have Python's truth-testing rules.

It's like list.append returning None. It helps catch errors.
 
S

Steven D'Aprano

There is a horrible (IMO) thing that Perl, Lua, and Javascript all do,
which is automatically convert strings to numbers, so "12"+3 = 15.
Python has the good sense to throw a type error if you attempt such an
addition, but it goes and converts various types to bool automatically,

No, what Python does is more subtle than that. An example using strings
will (I hope!) make it clear. Or possibly muddy the waters even more.

Compare converting strings to ints: the string "1" maps to the int 1, "2"
to 2, and so forth. There's a one-to-one map of string to int (modulo
unicode and whitespace issues), and since this is more or less a
universal standard, it's enshrined in the language.

Now consider converting strings to bools. Should "true" map to True? Or
"yes", "ja", "vrai", "waar", or something else? That's an application-
specific question, not a universal standard (not even a de facto
standard), and Python rightly avoids it.

What about "maybe" or "strawberry jam"? You can't convert "strawberry
jam" into True or False any more than you can convert it into an int.

What Python does instead is to accept *any* object in a context where
other languages (such as Pascal) would insist on a boolean. In practice,
that means branches (if) as well as the short-cut operators and, or, not.
The semantics of this is well-defined, and I trust I don't need to go
over it again.

In an expression like:

x and y

unlike Pascal, there is no requirement that x and y be booleans. This is
why I talk about x and y being used "in a boolean context", rather than
converting it to a bool. [3,4,5] is not, by any stretch of the
imagination, True converted into a list, and likewise [2,3,4] is a list
and can't be converted to a flag any more than it can be converted to an
int. But what I do say is that, according to Python's semantics, the list
[3,4,5] is equivalent to True in a boolean context.

Where Python muddies the water is to provide a bool() built-in which
*does* convert any object to canonical boolean form. bool([2,3,4])
returns True, which contradicts what I said above about not converting
the list into a flag. I accept this -- it's a triumph of practicality
over purity. It would be silly to force people to write:

# get the canonical form
if any_old_object:
flag = True
else:
flag = False

when we can say flag = bool(any_old_object).

One last thing -- we can see that Python does *not* convert objects to
bools "in a boolean context". The Python virtual machine really does
accept any object as an argument to and/or/not operators, as well as if:
1 0 LOAD_NAME 0 (a)
3 JUMP_IF_TRUE 4 (to 10)
6 POP_TOP
7 LOAD_NAME 1 (b) 11 LOAD_CONST 0 (None)
14 RETURN_VALUE


The JUMP_IF_TRUE opcode accepts any object, not just True or False.
 
I

Ian Kelly

You've seen -1 being used as false? Where? Are you still talking about
Python builtins or language semantics?

Some of our database tables at work use 1 for true, -1 for false, and
0 for neither. Don't look at me, I didn't design it. Why they didn't
just make the column nullable is beyond me, but that's the way it is.
 
S

Steven D'Aprano

It's like list.append returning None. It helps catch errors.
How?
.... print "myInt is not zero, safe to divide"
.... print 42/myInt
....
myInt is not zero, safe to divide
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
TypeError: unsupported operand type(s) for /: 'int' and 'str'



What error did this catch?
 
P

Paul Rubin

Steven D'Aprano said:
What Python does instead is to accept *any* object in a context where
other languages (such as Pascal) would insist on a boolean.

I'm aware of what Python does, just saying I can sympathize with the
sentiment that explicit conversions would make more sense. I wouldn't
change it in Python since it's what we're all used to, but if I were
designing a language from scratch I'd probably make it explicit.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top