Dino, There is no such things as a "principle of least surprise" or if you insist there is, I can nominate many more such "rules" such as "the principle of get out of my way and let me do what I want!"
Computer languages with too many rules are sometimes next to unusable in practical situations. I am neither defending or attacking choices Python or other languages have made. I merely observe and agree to use languages carefully and as documented. But consider that the history of computer science when it came to counting numbers depends on bits. Pretty much everything is in base two. When space was a major concern, or efficiency, people often used smaller units when possible. If you look at something like how one stored files on UNIX, they set aside a group of bits of some size as part of some larger entity and each bit represented a BOOLEAN concept of 1 and 0 to mean is that bit set to some sort of ON or off. Three of those bits controlled whether the owner of a file had permission to read, write or execute the file. Another three governed the same idea for everyone listed as being in the same group and another three listed permissions for "other". The whole thing took up more room in something larger where perhaps 14 bytes (of 8 bits each) were set aside to hold a filename and other parts held things like perhaps a link count. At some point they noticed the chink had a few unused bits and invented a purpose for them and patented the setuid bit concept and the setgid bit. So back to integers. You can use 16 bits in a signed or unsigned manner and cover numbers between a low and a high. You can use 64 bits or 128 bits or whatever makes you happy and it remains an integer albeit trying to do arithmetic between them can result in an overflow situation and the hardware often does not trivially support it. It turned out that often there was a use for 8 bits even though they hold only 256 possible integers and before the alphabets grew to need more room, that was enough space for an ASCII or EBCDIC character. Sometimes you did things at the nibble level of 4 bits or a hex digit. Booleans were even simpler at 1 bit. But all SIZES can be used to hold some range of integers. Modern python has made some extensions that let you store integers of unlimited size but underneath it all, the operations are still dealing with the same ideas as shorter versions including ones that hold more limited numbers down to binary/Boolean. So if you want to save space in memory or on a hard disk or sending across the internet, you well may want the ability to set aside a "char" to hold smallish numbers or treat a Boolean value as a "1" and so on. If you know what you are doing, it is not much of a surprise. On many systems, there may well be some registers that load 32 or 64 bits and then you use them for something like addition. If I supply a 16-bit or 8-bit or even 1-bit quantity, the software generally ends up putting it into the standard size register and pads unused areas with zeroes. No big deal. If the number is too large to fit, as with any larger integer in python, then the software does whatever it needs to such as calculating how many chunks need adding and doing the addition in the same registers in smaller chunks while managing any carryover and finally assembling the possibly longer result. Floating point is a slightly different animal than the others that arguably are all of a similar if not identical type. But even there, your storage has two components which are actually both seen as integers of sorts. 6.02 times ten to the 23rd might also be written as 602 times ten to the 21st and now you have two integers you can use in calculations that registers do on integers and recombine into a new floating point format. Or, of course, you might have hardware that does the work. If you move on to complex variables, they tend to be a sort of named tuple containing a real and imaginary part with special rules on how to add and do other mathematical operations. Underneath it all, they are often implemented as a pair of linked floating point structures. And in one sense, all real numbers represented in a floating point variable are a strict subset of complex numbers with imaginary part being zero. All integers are in a sense floating point numbers with fractional part (meaning beyond the decimal point) being all zeroes. Similarly, all smaller integral types such as bytes are Booleans are a limited subset. So some of us who know a bit about CS and not just this language, are less often surprised by a choice of implementations. We often do not mix things but when we do, we know what we are doing much of the time and appreciate how easily it can be done. Consider what happens if you want to circularly permute alphabetic characters of the English Alphabet by 13, sometimes called rot13. There are quite a few ways to do it but one of them depends on the fact that the numerical value in ASCII of the letter 'A' is one less than of the next letter, 'B' and so on to 'Z'. They are contiguous but note upper and lower cases letters are not back to back. So a piece of code that says that if a character is between the numerical representation of 'A' and halfway to the end, then add 13, and if it is higher, then add 13 and subtract 26 (or obviously just subtract 13) to slide it circularly back, is a valid way to do the permutation. But it involves adding what may seem to be a 32-bit integer containing a number like 13 or 26 to an 8-bit character resulting in an 8-bit character. Should that be illegal? Well, in a sense it is illegal and you should be forced to create something of type char that holds whatever 13 is, which probably is a control-character and then either use operations that add or subtract 8-bit items, OR you may widen the character to 32 bits and do the math with a 32-bit representation of 13/26 then narrow the result back into eight bits. But lots of systems know how to automate this for you or even do it more efficiently than you might have done on your own and do it differently on different computer architectures. One goal of programming is to make life as easy as possible for a programmer to be productive or make fewer errors and so on. Sometimes not being surprised is a valid goal. But a language like Python may not lean the way you think. I once bashed my head at languages like PASCAL and even C as it often took some work to do things like process a list of heterogenous contents including perhaps some I may have no idea about at compile time. You sometimes needed to convince the compiler to loosen up on rules such as by declaring a union of several types. Python often does not care what anything is and just passes it on. You, as the writer of a function may have to check things like whether what you were passed is hashable or is of a numeric type. You may simply take any argument(s) and coerce them into a new list object to guarantee that whatever it is can now handle what lists supply. This means you are often free to use the function with arguments that are tuples or iterators and not just lists. Yes, someone using the function may yet surprise you and you may want to write defensive code that checks up-front and stops if called in an unexpected way. But you can write the main function fairly quickly while assuming no surprises and bullet-proof it later once it seems to work for what you want. The alternative is to keep fighting with a compiler (or a static checker like mpy) before anything gets done. The surprise there is when they fire you from your job for not seeming to do much for many months. Having said that, I have had many surprises in many languages such as some that help you so much that they handle 3 + "two" for you and return 5 or maybe "five" rather than suggest you may have name an error and meant 3 + int(english_number_to_string("two")) or perhaps "3" + "two" ... I am surprised how this message got this long! Aaargh! -----Original Message----- From: Python-list <python-list-bounces+avi.e.gross=gmail....@python.org> On Behalf Of Dino Sent: Wednesday, January 25, 2023 3:33 PM To: python-list@python.org Subject: Re: bool and int On 1/23/2023 11:22 PM, Dino wrote: > >>> b = True > >>> isinstance(b,bool) > True > >>> isinstance(b,int) > True > >>> ok, I read everything you guys wrote. Everyone's got their reasons obviously, but allow me to observe that there's also something called "principle of least surprise". In my case, it took me some time to figure out where a nasty bug was hidden. Letting a bool be a int is quite a gotcha, no matter how hard the benevolent dictator tries to convince me otherwise! -- https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list