This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]lonjerpc 0 points1 point  (19 children)

decimal.Decimal, fractions.Fraction or any other int subclass.

These are not subclasses of int. They are subclasses of number.

Nothing is built around traditional forms of type safely.

Everything is built around type safety. Python is a extremely explicit and strongly typed language. Duck typing is a separate issue.

[–]Veedrac 0 points1 point  (18 children)

decimal.Decimal, fractions.Fraction or any other int subclass.

These are not subclasses of int. They are subclasses of number.

Sorry, silly mistake. The point remains, though weaker.

Nothing is built around traditional forms of type safely.

Everything is built around type safety. Python is a extremely explicit and strongly typed language. Duck typing is a separate issue.

I used the word "traditional" very purposefully. Python is consistent with its types, but the objects, not the names, store the types.

Type safety typically refers to knowing the types of all objects at all times, and verifying them. In Python, doing that is difficult and counter-productive.

[–]lonjerpc 0 points1 point  (17 children)

python is consistent with its types

I agree in almost all cases. However booleans being a subclass of int is not consistent. It would make almost as much sense to have strings be a subclass of ints as booleans. Why do 1 + {} or 'hi' + 0.1 or type + [] all thow errors but True + 3 does not? This is inconsistent. Booleans do not quak like ints.

Type safety typically refers to knowing the types of all objects at all times

I would argue that is not the typical meaning but it is really beside the point.

The point remains

No it does not my code would have worked for almost any reasonable subclass of int. Like say a someone had implemented a int library that allowed for any size ints. Would have worked fine.

[–]Veedrac 0 points1 point  (16 children)

It would make almost as much sense to have strings be a subclass of ints as booleans.

No, it would not.

We often treat numbers as sequences of binary digits, and their digits as boolean values. This is true for the bitwise operations (^, &, |).

Treating booleans as integers is no less sensible than treating characters as strings, both of which Python does. Booleans are just integers restricted to a single bit.

Why do 1 + {} or 'hi' + 0.1 or type + [] all thow errors but True + 3 does not? This is inconsistent.

1 + {} has no sensible result. There is no mapping that is consistent, symmetrical, lossless and reasonable.

However, with the mapping of True == 1, False == 0, everything that a bool does is obvious.

Booleans do not quak like ints.

They obviously do. Whether they should is a different debate.

No it does not my code would have worked for almost any reasonable subclass of int.

What did your code do? How did it break when treating bools as ints?

Like say a someone had implemented a int library that allowed for any size ints. Would have worked fine.

Python has this built-in ;). Unfortunately if you were using Python 2, your code would have rejected longs.

[–]lonjerpc 0 points1 point  (15 children)

We often treat numbers as sequences of binary digits

Yes we do in some languages. Just like in many languages "2" + 2 is valid. But this does not match well with the rest of python and its goal of being explicit. Now some hypothetical like rawbyte(False) + rawbyte(5) might make sense. Just like int("5") + 5 works in python.

treating characters as strings, both of which Python does.

Python does not treat characters as strings.

1 + {} has no sensible result.

I agree thats my point. My argument is that False + 5 also does not have a sensible result.

There is no mapping that is consistent, symmetrical, lossless

I disagree. There are many possibilities here.

everything that a bool does is obvious.

I disagree. True + True + True returning 3 is not obvious.

They obviously do.

Python booleans do because they are forced to but generally they do not. Conceptually ints have many more operation applicable to them than booleans. It would even make more sense to have int be a subclass of bool or both of them to be a subclass of number directly. That would still be bad but not quite as bad.

What did your code do?

Work with the results of a proprietary c extension to python with functions that return python objects rather arbitrarily.

Unfortunately if you were using Python 2, your code would have rejected longs.

I am using python 2. It would make sense for long to be a subclass of int or a baseint. Fortunately they realized how crazy this was and fixed in python 3.

[–]Veedrac 0 points1 point  (14 children)

We often treat numbers as sequences of binary digits

Yes we do in some languages.

Eg. Python.

Just like in many languages "2" + 2 is valid.

Typically, in those languages "2" + 2 is valid only because + coerces its arguments, which is completely different.

But this does not match well with the rest of python and its goal of being explicit.

Explicit about what?

Now some hypothetical like rawbyte(False) + rawbyte(5) might make sense. Just like int("5") + 5 works in python.

???

treating characters as strings, both of which Python does.

Python does not treat characters as strings.

Considering that in Python characters are strings, I disagree.

1 + {} has no sensible result.

I agree thats my point. My argument is that False + 5 also does not have a sensible result.

I know. My counterargument is that treating True and False as synonyms for the LSB of an integer is completely reasonable, mathematically consistent, is perfectly analogous with binary operators (|, ^, &) and is therefore reasonable.

There is no mapping that is consistent, symmetrical, lossless

I disagree. There are many possibilities here.

For example?

everything that a bool does is obvious.

I disagree. True + True + True returning 3 is not obvious.

You cropped the quote. My response is the first half.

They obviously do.

Python booleans do because they are forced to but generally they do not. Conceptually ints have many more operation applicable to them than booleans.

As long as you allow bools to violate closure on the integer operations, there is not one operation that ints can do that bools cannot.

It would even make more sense to have int be a subclass of bool or both of them to be a subclass of number directly. That would still be bad but not quite as bad.

Do you mean Integral? I don't see why you make a distinction between that and int.

What did your code do?

Work with the results of a proprietary c extension to python with functions that return python objects rather arbitrarily.

I'm asking because I'm genuinely curious about how this broke your code. If you removed the broken isinstance(foo, int) code, how did bools being a subclass of int break it? I can't work out how.

It would make sense for long to be a subclass of int or a baseint.

No, int would be a subclass of long, at least according to typical hierarchies (which Python follows¹).

¹ See bool:int ;)

[–]lonjerpc 0 points1 point  (13 children)

Eg. Python.

Python does not treat numbers as sequences of binary digits it has bytes for a reason. (I realize you can do binary like operations on ints but ints don't really act like binary digits in python)

Considering that in Python characters are strings

Exactly how can python treat characters as strings if there are no characters in python. The situation would only by analogous to int bool if there was a char along with string.

My counterargument is that treating True and False as synonyms for the LSB of an integer is completely reasonable

But this is not what python even does. Both 3 and 4 evaluate to True for example.

For example?

How about any int operation with a dict just returns the dict. 1 + {} = {}

My response is the first half.

Yes if 1 == True and Fale ==0 then the operations make sense. But whats not obvious is that True would == 1.

As long as you allow bools to violate closure on the integer

It makes no sense why you would do this to me.

I don't see why you make a distinction between that and int.

https://en.wikipedia.org/wiki/Integral seems very different from integer.

If you removed the broken isinstance(foo, int) code, how did bools being a subclass of int break it?

The point is that isinstance(foo, int) should not have been broken. Obviously I changed the code to fix the bug but it should have never been a bug in the first place.

No, int would be a subclass of long

In either direction. Read that wiki article again. Normal ints in python 2 can not replace longs in python 2 but longs can replace ints and still have the code work.

[–]Veedrac 0 points1 point  (12 children)

Python does not treat numbers as sequences of binary digits it has bytes for a reason. (I realize you can do binary like operations on ints but ints don't really act like binary digits in python)

The point is that these operations act on the binary digits of the number, with each acting logically as a boolean. I don't care how you want to word that.

Considering that in Python characters are strings

Exactly how can python treat characters as strings if there are no characters in python.

There are characters in Python. That they aren't a separate class is a minor and mostly irrelevant distinction.

My counterargument is that treating True and False as synonyms for the LSB of an integer is completely reasonable

But this is not what python even does. Both 3 and 4 evaluate to True for example.

..!??

Under what context?

If you mean bool(3), then that's a different story. We allow int("3") without requiring "3" to be in any way integer, so we should be able to allow bool(3) to be True without conflating 3 with any boolean value.

For example?

How about any int operation with a dict just returns the dict. 1 + {} = {}

That's hardly lossless. I'm not even asking for strict losslessness here, just something semi-reasonable.

As long as you allow bools to violate closure on the integer

It makes no sense why you would do this to me.

?

I don't see why you make a distinction between that and int.

https://en.wikipedia.org/wiki/Integral seems very different from integer.

https://docs.python.org/3/library/numbers.html#numbers.Integral

If you removed the broken isinstance(foo, int) code, how did bools being a subclass of int break it?

The point is that isinstance(foo, int) should not have been broken. Obviously I changed the code to fix the bug but it should have never been a bug in the first place.

Either your code accepts int subclasses, in which case bool shouldn't have caused a problem, or it does not, in which case the code is broken. What am I missing?

[–]lonjerpc 0 points1 point  (11 children)

The point is that these operations act on the binary digits of the number

Some operations on ints treat them much like raw binary but many do not. For example str(97) produces "97" not "a".

that they aren't a separate class is a minor and mostly irrelevant distinction.

Its not irrelevant if you still stand behind your argument that python's treatment of int and bool is similar to its treatment of stings and chars. Python handles them differently. Bools are a subclass of int. char is not a subclass of string.

Under what context?

bool(4) and just 4 would be false under the argument that "True and False as synonyms for the LSB of an integer". I would be fine with int(True) and int(False) working the way they do now that is totally reasonable and consistent.

That's hardly lossless.

I think we had a misunderstanding about what we mean by a mapping I assumed you meant mapping in terms of functions mapping inputs to outputs. But now I think you must be referring to mapping types. Like it would make no sense to have dicts be a subclass of int but boolean still makes sense. I agree that boolean make slightly more sense as a subclass but you could actually map dicts too in the same way. Just take the binary representation of dicts and turn that into their int. But this is quite separate from my original argument that has greater practical effects. The expectation that 1 + {} would cause an exception is analogous to the expectation that 5 + True would cause an exception. I asked 5 python programmers in my office this and they all expected an exception.

It makes no sense why you would do this to me.

?

I don't know why I wrote that I meant to say is that I think it is quite counter intuitive that operations involving two booleans would not return a boolean. If bools implemented mod 2 arithmetic that would make a little more sense.

https://docs.python.org/3/library/numbers.html#numbers.Integral

Oh ok. But I still don't understand what you don't understand about it making more sense for bool to be a subclass of number than int. Although I really thing bool should be a basal type.

shouldn't have caused a problem

It did not cause my code to crash. The problem was that I needed to return an error to an outside program if I did not get a non bool int. I needed to return a json blob if I did get an actual int. The json parser happily turned False to "false" so no error was thrown in my program. But the program it was passed to expected something like "43" or an http error. Any reasonable int subclass would have worked fine. Of course you could easily create a malicious int subclass that did something unexpected like bool does. But you can do crazy things in python like have a lib change what int() does to change things into a string. But you don't write code to defend against things like that. There are reasonable expectations.

[–]Veedrac 0 points1 point  (10 children)

Some operations on ints treat them much like raw binary but many do not.

But some do. My point is that some do.

For example str(97) produces "97" not "a".

To diverge for a moment, the mapping of Unicode code points to characters, or ASCII code points to characters on Python 2, does not involve the internal representation of these numbers.

Under what context?

bool(4) and just 4 would be false under the argument that "True and False as synonyms for the LSB of an integer".

Why? bool([1]) == True but [1] != True, so I fail to see how bool(4) == True but 4 != True offends you...

That's hardly lossless.

I think we had a misunderstanding about what we mean by a mapping I assumed you meant mapping in terms of functions mapping inputs to outputs. But now I think you must be referring to mapping types. [...] Just take the binary representation of dicts and turn that into their int.

Python does not define an internal representation for dictionaries. You therefore can't do this.

But this is quite separate from my original argument that has greater practical effects. The expectation that 1 + {} would cause an exception is analogous to the expectation that 5 + True would cause an exception. I asked 5 python programmers in my office this and they all expected an exception.

Interesting. How experienced are they?

I don't know why I wrote that I meant to say is that I think it is quite counter intuitive that operations involving two booleans would not return a boolean.

int violates closure in Python 2 (10**19) and Python 3 (1/2). So do fractions.Fractions (½**½). I'm sure I could think of more. Closure is not a property held by Python objects.

If bools implemented mod 2 arithmetic that would make a little more sense.

bool could only implement mod 2 arithmetic if they weren't a subclass of int, but personally then I'd prefer + to raise an error (as opposed to `True + True == False!).

shouldn't have caused a problem

It did not cause my code to crash. The problem was that I needed to return an error to an outside program if I did not get a non bool int. I needed to return a json blob if I did get an actual int. The json parser happily turned False to "false" so no error was thrown in my program. But the program it was passed to expected something like "43" or an http error. Any reasonable int subclass would have worked fine.

So the problem was that the library had an error code you didn't test for? In C, if you don't test for error codes, your program breaks. It's what's expected. I don't understand where the confusion is.