Should bool continue to inherit from int?
PEP 285 <http://legacy.python.org/dev/peps/pep-0285> provides some justification for why arithmetic operations should be valid on bools and why bool should inherit from int (see points (4) and (6) respectively). Since it's been 12 years (it's possible this has been brought up again between now and then), I thought it could be worthwhile to take another look. I am mostly interested in a resurveying of the questions: 1) Would it still be very inconvenient to implement bools separately from ints? 2) Do most Python users still agree that arithmetic operations should be supported on booleans? Follow-up thought: Something I noticed is that with PEP 484 <https://www.python.org/dev/peps/pep-0484/> (Type Hints) specified as is, there would be no way to statically verify that a function will only operate on ints and not bools. An example would be a function that can only operate on integer values in a JSON dict created by the builtin `json` module (using the default decoder) cannot exist, as that function could operate on the boolean values of the dict.
On Wed, Jan 21, 2015 at 03:32:49AM -0800, Michael Mitchell wrote:
PEP 285 <http://legacy.python.org/dev/peps/pep-0285> provides some justification for why arithmetic operations should be valid on bools and why bool should inherit from int (see points (4) and (6) respectively). Since it's been 12 years (it's possible this has been brought up again between now and then), I thought it could be worthwhile to take another look.
I am mostly interested in a resurveying of the questions: 1) Would it still be very inconvenient to implement bools separately from ints?
Yes, it would break a lot of code that for the last twelve years has relied on being able to perform arithmetic on bools. Arguably, Python 3 might have been the opportunity to break that backwards compatibility, but we're up to 3.4 now so we would need a very good reason to do so.
2) Do most Python users still agree that arithmetic operations should be supported on booleans?
I don't know about "most", but this Python user thinks so.
Follow-up thought: Something I noticed is that with PEP 484 <https://www.python.org/dev/peps/pep-0484/> (Type Hints) specified as is, there would be no way to statically verify that a function will only operate on ints and not bools.
If you want an int, I'm not sure why you would want to exclude bools since they are ints.
An example would be a function that can only operate on integer values in a JSON dict created by the builtin `json` module (using the default decoder) cannot exist, as that function could operate on the boolean values of the dict.
I'm afraid I don't quite follow this example. Can you give some sample code (with or without annotations)? -- Steve
On 21/01/2015 12:44, Joao S. O. Bueno wrote:
Should bool continue to inherit from int? yes.
Except when your (plural) definition of bool differs from mine, as was seen recently over on the main Python mailing list. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence
On Wed, Jan 21, 2015 at 10:32 PM, Michael Mitchell <epsilonmichael@gmail.com> wrote:
PEP 285 provides some justification for why arithmetic operations should be valid on bools and why bool should inherit from int (see points (4) and (6) respectively). Since it's been 12 years (it's possible this has been brought up again between now and then), I thought it could be worthwhile to take another look.
I am mostly interested in a resurveying of the questions: 1) Would it still be very inconvenient to implement bools separately from ints? 2) Do most Python users still agree that arithmetic operations should be supported on booleans?
We recently had a thread on python-list about this. There are a number of useful operations that can be done on bools-as-integers (such as summing them to quickly and efficiently figure out how many are True). But let me rephrase your question: "Python's booleans currently support arithmetic operations. Should we no longer support them?" Even leaving aside the massive backward compatibility implications (which would probably mean this kind of removal can't be done until Python 4.0 or 5.0 or who-knows-when), the philosophical question of "why should we NOT support something" needs a strongly-justified answer. Sure, it might make sense to have a non-integer type for the two special objects True and False; but what would the language gain by it? It's quite common for 1 and 0 to *be* the language's True and False values. REXX has no types, but in a boolean context, any value other than 1 or 0 triggers an error; C doesn't have a boolean type, and comparisons return 1 or 0; C++ has a boolean type, but will cheerfully and silently up-cast it to integer if you do arithmetic on it; Pike uses 1 and 0 (parallel to C), and allows any object to declare its own "truthiness" (more-or-less equivalently to Python's __bool__ method). All of them allow you to write stuff like: if (((1==1) + (1==0) + (0==0)) == 2) which will be true (if a little over-parenthesized for some people's liking). These kinds of constructs allow you to do fuzzy matching fairly efficiently - imagine the three conditions are three different search criteria, and instead of simply seeing if the sum is 2, you sort a large number of results by that sum. The more conditions match, the greater the sum. Sure, this isn't a *common* requirement, but what would the language really gain by forcing you to intify with something like "lambda b: 1 if b else 0"? ChrisA
On 2015-01-21 13:27, Chris Angelico wrote:
On Wed, Jan 21, 2015 at 10:32 PM, Michael Mitchell <epsilonmichael@gmail.com> wrote:
PEP 285 provides some justification for why arithmetic operations should be valid on bools and why bool should inherit from int (see points (4) and (6) respectively). Since it's been 12 years (it's possible this has been brought up again between now and then), I thought it could be worthwhile to take another look.
I am mostly interested in a resurveying of the questions: 1) Would it still be very inconvenient to implement bools separately from ints? 2) Do most Python users still agree that arithmetic operations should be supported on booleans?
We recently had a thread on python-list about this. There are a number of useful operations that can be done on bools-as-integers (such as summing them to quickly and efficiently figure out how many are True). But let me rephrase your question:
"Python's booleans currently support arithmetic operations. Should we no longer support them?"
Even leaving aside the massive backward compatibility implications (which would probably mean this kind of removal can't be done until Python 4.0 or 5.0 or who-knows-when), the philosophical question of "why should we NOT support something" needs a strongly-justified answer. Sure, it might make sense to have a non-integer type for the two special objects True and False; but what would the language gain by it?
It's quite common for 1 and 0 to *be* the language's True and False values. REXX has no types, but in a boolean context, any value other than 1 or 0 triggers an error; C doesn't have a boolean type, and comparisons return 1 or 0; C++ has a boolean type, but will cheerfully and silently up-cast it to integer if you do arithmetic on it; Pike uses 1 and 0 (parallel to C), and allows any object to declare its own "truthiness" (more-or-less equivalently to Python's __bool__ method). All of them allow you to write stuff like:
if (((1==1) + (1==0) + (0==0)) == 2)
which will be true (if a little over-parenthesized for some people's liking). These kinds of constructs allow you to do fuzzy matching fairly efficiently - imagine the three conditions are three different search criteria, and instead of simply seeing if the sum is 2, you sort a large number of results by that sum. The more conditions match, the greater the sum. Sure, this isn't a *common* requirement, but what would the language really gain by forcing you to intify with something like "lambda b: 1 if b else 0"?
Pascal has 'ord' for getting the ordinal number from an enumerated type, so perhaps that could be used: ord(False) == 0 ord(True) == 1 Currently it's just the inverse of 'chr'.
On Wed, Jan 21, 2015 at 06:12:13PM +0000, MRAB wrote:
Pascal has 'ord' for getting the ordinal number from an enumerated type, so perhaps that could be used:
ord(False) == 0 ord(True) == 1
Currently it's just the inverse of 'chr'.
In Python, that is spelled int(False) # returns 0 int(True) # returns 1 -- Steve
Chris Angelico wrote:
All of them allow you to write stuff like:
if (((1==1) + (1==0) + (0==0)) == 2)
Packing a number of booleans into an int is another case where bool-int equivalence comes in handy. I've found myself annoyed by this in Java on more than one occasion recently. (Java neither allows bools to be used as ints nor non-bools to be used directly as truth values.) -- Greg
On 21/01/2015 13:27, Chris Angelico wrote:
On Wed, Jan 21, 2015 at 10:32 PM, Michael Mitchell <epsilonmichael@gmail.com> wrote:
PEP 285 provides some justification for why arithmetic operations should be valid on bools and why bool should inherit from int (see points (4) and (6) respectively). Since it's been 12 years (it's possible this has been brought up again between now and then), I thought it could be worthwhile to take another look.
I am mostly interested in a resurveying of the questions: 1) Would it still be very inconvenient to implement bools separately from ints? 2) Do most Python users still agree that arithmetic operations should be supported on booleans? All of them allow you to write stuff like:
if (((1==1) + (1==0) + (0==0)) == 2)
which will be true (if a little over-parenthesized for some people's liking). May I offer a more realistic example, adapted from a real-life program:
ST1 = '20:00' ET1 = '22:00' ST2 = '22:00' ET2 = '06:00' # These variables represent times of day (24-hour clock). # We want to check that [ST1, ET1) and [ST2, ET2) are non-empty, non-overlapping time periods, # (allowing the time to wrap past midnight) as they are in this example # (the time periods are considered to include the *S*tart *T*ime but not the *E*nd *T*ime). # A naive approach might be: if ( (ST1 < ET1 <= ST2 < ET2) or (ET2 <= ST1 < ET1 <= ST2) or (ST2 < ET2 <= ST1 < ET1) or (ET1 <= ST2 < ET2 <= ST1) ): <time intervals are OK> # but this can be coded much more succinctly if at first sight less transparently (and sorry, Chris, without redundant parentheses :-) ) as: if (ST1<ET1) + (ET1 <= ST2) + (ST2<ET2) + (ET2<=ST1) == 3: <time intervals are OK> # Lines 1,2,3,4 in the naive approach correspond exactly # to the cases where only the 4th/3rd/2nd/1st term, respectively, # is False in the succinct approach. So arithmetic on booleans may not be "pure" but it can be handy.
On Thu, Jan 22, 2015 at 12:10 PM, Rob Cliffe <rob.cliffe@btinternet.com> wrote:
# but this can be coded much more succinctly if at first sight less transparently (and sorry, Chris, without redundant parentheses :-) ) as:
The extra parens were just because I was listing a bunch of languages, and the exact same statement would work in all of them (although Python would expect a colon at the end, and REXX would be looking for a 'THEN' on that or the next line). :) I wouldn't normally put the extra parens in a Python program. ChrisA
Might not be the best example because there exists a comparably concise way without using addition: if all([ST1 < ET1, ST2 < ET2, ET2 <= ST1 or ET1 <= ST2]): <time intervals are okay> but I do see the point On Wed, Jan 21, 2015 at 5:10 PM, Rob Cliffe <rob.cliffe@btinternet.com> wrote:
On 21/01/2015 13:27, Chris Angelico wrote:
On Wed, Jan 21, 2015 at 10:32 PM, Michael Mitchell<epsilonmichael@gmail.com> <epsilonmichael@gmail.com> wrote:
PEP 285 provides some justification for why arithmetic operations should be valid on bools and why bool should inherit from int (see points (4) and (6) respectively). Since it's been 12 years (it's possible this has been brought up again between now and then), I thought it could be worthwhile to take another look.
I am mostly interested in a resurveying of the questions: 1) Would it still be very inconvenient to implement bools separately from ints? 2) Do most Python users still agree that arithmetic operations should be supported on booleans?
All of them allow you to write stuff like:
if (((1==1) + (1==0) + (0==0)) == 2)
which will be true (if a little over-parenthesized for some people's liking).
May I offer a more realistic example, adapted from a real-life program:
ST1 = '20:00' ET1 = '22:00' ST2 = '22:00' ET2 = '06:00' # These variables represent times of day (24-hour clock). # We want to check that [ST1, ET1) and [ST2, ET2) are non-empty, non-overlapping time periods, # (allowing the time to wrap past midnight) as they are in this example # (the time periods are considered to include the *S*tart *T*ime but not the *E*nd *T*ime). # A naive approach might be: if ( (ST1 < ET1 <= ST2 < ET2) or (ET2 <= ST1 < ET1 <= ST2) or (ST2 < ET2 <= ST1 < ET1) or (ET1 <= ST2 < ET2 <= ST1) ):
<time intervals are OK>
# but this can be coded much more succinctly if at first sight less transparently (and sorry, Chris, without redundant parentheses :-) ) as:
if (ST1<ET1) + (ET1 <= ST2) + (ST2<ET2) + (ET2<=ST1) == 3:
<time intervals are OK>
# Lines 1,2,3,4 in the naive approach correspond exactly # to the cases where only the 4th/3rd/2nd/1st term, respectively, # is False in the succinct approach.
So arithmetic on booleans may not be "pure" but it can be handy.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
On 01/21/2015 03:32 AM, Michael Mitchell wrote:
1) Would it still be very inconvenient to implement bools separately from ints?
Extremely. Lots of code relies on the int properties of bool.
2) Do most Python users still agree that arithmetic operations should be supported on booleans?
I certainly do. It might be nice from an ivory-tower perspective to keep bools separate from ints, but in a Practicality Beats Purity world it is quite handy. -- ~Ethan~
On Wed, Jan 21, 2015 at 3:32 AM, Michael Mitchell <epsilonmichael@gmail.com> wrote:
PEP 285 <http://legacy.python.org/dev/peps/pep-0285> provides some justification for why arithmetic operations should be valid on bools and why bool should inherit from int (see points (4) and (6) respectively). Since it's been 12 years (it's possible this has been brought up again between now and then), I thought it could be worthwhile to take another look.
I am mostly interested in a resurveying of the questions: 1) Would it still be very inconvenient to implement bools separately from ints? 2) Do most Python users still agree that arithmetic operations should be supported on booleans?
It would be so massively backward compatible that it's not worth thinking about.
Follow-up thought: Something I noticed is that with PEP 484 <https://www.python.org/dev/peps/pep-0484/> (Type Hints) specified as is, there would be no way to statically verify that a function will only operate on ints and not bools. An example would be a function that can only operate on integer values in a JSON dict created by the builtin `json` module (using the default decoder) cannot exist, as that function could operate on the boolean values of the dict.
Like Steven, I can't completely follow this thought (it looks like you were writing too fast and jumbled a few verbs or negations) but you bring up an interesting point: even though bools are ints, their JSON encodings are different. So I believe you are saying, suppose I have a function that takes an integer argument and then JSON-encodes it and sends it to some server that requires a JSON int. Now suppose you are adding type hints to your code, and you add ": int" to the parameter under discussion. And now suppose you have a faulty caller which calls this function with the argument set to True. This program will type-check correctly, because True is a bool which is a subclass of int, but it will run incorrectly, because (under this assumption) True will be converted to a JSON true value, which the server rejects. TBH I have to think about this more. I think that in the initial version of PEP 484 we won't try to address this (JSON without something that enforces a schema is too dynamic to fit well into any type system), but I've opened an issue to have a further discussion about this: https://github.com/ambv/typehinting/issues/52 -- --Guido van Rossum (python.org/~guido)
On Wed, Jan 21, 2015 at 2:11 PM, Guido van Rossum <guido@python.org> wrote:
2) Do most Python users still agree that arithmetic operations should be
supported on booleans?
It would be so massively backward compatible that it's not worth thinking about.
The only time I encountered a situation where True + True was not 2 was in numpy:
numpy.bool_(True) + True True
That was *very* inconvenient!
From a mathematician's standpoint Booleans are the ring of integers modulo
What did you expect? It can't be 2 since np.bool is free to be a one-bit type. It shouldn't promote. If anything it should probably be False in my opinion just like np.int8(255) + 1 == 0 2. On this proposal, I agree with the people saying it's too backwards incompatible, but from an ivory tower standpoint it would have been better. Best, Neil On Wednesday, January 21, 2015 at 2:50:00 PM UTC-5, Alexander Belopolsky wrote:
On Wed, Jan 21, 2015 at 2:11 PM, Guido van Rossum <gu...@python.org <javascript:>> wrote:
2) Do most Python users still agree that arithmetic operations should be
supported on booleans?
It would be so massively backward compatible that it's not worth thinking about.
The only time I encountered a situation where True + True was not 2 was in numpy:
numpy.bool_(True) + True True
That was *very* inconvenient!
On Wed, Jan 21, 2015 at 11:11 AM, Guido van Rossum <guido@python.org> wrote:
So I believe you are saying, suppose I have a function that takes an integer argument and then JSON-encodes it and sends it to some server that requires a JSON int. Now suppose you are adding type hints to your code, and you add ": int" to the parameter under discussion. And now suppose you have a faulty caller which calls this function with the argument set to True. This program will type-check correctly, because True is a bool which is a subclass of int, but it will run incorrectly, because (under this assumption) True will be converted to a JSON true value, which the server rejects.
This sounds like it may benefit from the issue under discussion for Cython -- a way to specify an int only, and not allow subclasses. Though I suppose in this case, you may want to allow other subclasses, just not that one. This hypothetical code could also to a cast/conversion to int anyway, which is pretty much how you'd do it with duck typing and no type checking. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov
On Wed, Jan 21, 2015 at 11:11 AM, Guido van Rossum <guido@python.org> wrote:
So I believe you are saying, suppose I have a function that takes an integer argument and then JSON-encodes it and sends it to some server that requires a JSON int. Now suppose you are adding type hints to your code, and you add ": int" to the parameter under discussion. And now suppose you have a faulty caller which calls this function with the argument set to True. This program will type-check correctly, because True is a bool which is a subclass of int, but it will run incorrectly, because (under this assumption) True will be converted to a JSON true value, which the server rejects.
This is much better phrased than what I had written, thanks :) I'll be watching the Github issue. Thank you to everyone that replied. My impression is that the rationale in PEP 285 still holds strong.
Guido van Rossum wrote:
And now suppose you have a faulty caller which calls this function with the argument set to True. This program will type-check correctly, because True is a bool which is a subclass of int, but it will run incorrectly, because (under this assumption) True will be converted to a JSON true value, which the server rejects.
This could be regarded as just one of the many things that static type checking can't catch, and needs to be checked at run time. However, with something like the exactly() function suggested earlier, the required type could be described statically. -- Greg
On 1/21/2015 6:32 AM, Michael Mitchell wrote:
PEP 285 <http://legacy.python.org/dev/peps/pep-0285> provides some justification for why arithmetic operations should be valid on bools and why bool should inherit from int (see points (4) and (6) respectively). Since it's been 12 years (it's possible this has been brought up again between now and then), I thought it could be worthwhile to take another look.
I am mostly interested in a resurveying of the questions: 1) Would it still be very inconvenient to implement bools separately from ints? 2) Do most Python users still agree that arithmetic operations should be supported on booleans?
python-list would be a better place for this discussion. -- Terry Jan Reedy
participants (14)
-
Alexander Belopolsky
-
Chris Angelico
-
Chris Barker
-
Ethan Furman
-
Greg Ewing
-
Guido van Rossum
-
Joao S. O. Bueno
-
Mark Lawrence
-
Michael Mitchell
-
MRAB
-
Neil Girdhar
-
Rob Cliffe
-
Steven D'Aprano
-
Terry Reedy