9 ms·
In most languages, `x: float = 0` involves an implicit conversion from int to float. In Python, type annotations have no impact on runtime behavior, so even tho
by dgrunwald 6mo ago
In most languages, `x: float = 0` involves an implicit conversion from int to float. In Python, type annotations have no impact on runtime behavior, so even though the type checker accepts this code, `type(x)` will be `int` -- python acts as if `int` was a subtype of `float`.
It would be weird if the behavior of `1 / x` was different depending on whether `0` or `0.0` was passed to a `x: float` parameter -- if `int` is a subtype of `float`, then any operation allowed on `float` (e.g. division) should have the same behavior on both types.
This means Python had to choose at least one:
1. division violates the liskov substitution principle
2. division by zero involving only integer inputs returns NaN
3. division by zero involving only float inputs throws
exception
4. It's a type error to pass an int where a float is expected.
They went with option 3, and I think I agree that this is the least harmful/surprising choice. Proper statically typed languages don't have to make this unfortunate tradeoff.
- Aardwolf 6mo agoC does different things for 0.0 / 0.0 and 0 / 0 and it's not that weird to deal with (well it has other issues like it being platform dependent what happens with this). JS has no problem with it either (0.0 / 0.0 gives nan, 0n / 0n gives exception since it are integers). Python is the only language doing this (of the ones I use at least). I don't think the notation `x: float = 0` existed when it was new by the way so that can't be the design reason? since python seems to handle integer through integer divisions as float (e.g. 5 / 2 outputs 2.5), 0 / 0 giving nan would seem to be expected there > liskov substitution principle that would imply one is a subtype of another, is that really the case here? there are floats that can't be represented as an integer (e.g. 0.5) and integers that can't be represented as a double precision float (e.g. 18446744073709551615)
- kbolino 6mo agoPython chose, quite some time ago, not to follow C's lead on division: PEP 238 – Changing the Division Operator (2001) [1] The rationale is basically that newcomers to Python should see the results that they would expect from grade school mathematics, not the results that an experienced programmer would expect from knowing C. While the PEP above doesn't touch on division by zero, it does point toward the objective being a cohesive, layman-friendly numeric system. [1]: https://peps.python.org/pep-0238/ https://peps.python.org/pep-0238/
- xigoi 6mo agoC and JavaScript both treat integers and floats as separate types. In Python, ints and floats with the same numeric value are considered identical for almost all purposes.
- dgrunwald 6mo agoYes `int` acts as if it was a subtype of `float`: https://typing.python.org/en/latest/spec/special-types.html#special-cases-for-float-and-complex https://typing.python.org/en/latest/spec/special-types.html#...
- paulddraper 6mo ago> In Python, type annotations have no impact on runtime behavior That's true of any "scripting" language types. E.g. TypeScript const x: number = 0n; // still is a bigint Granted, in both the Python and the TypeScript example, the type checker will complain at your incorrect type annotation.
- dgrunwald 6mo agoBut in Python the type checker does not complain about `x: float = 0`, because for the purpose of type checking (but not at runtime), `int` is considered a subtype of `float`: https://typing.python.org/en/latest/spec/special-types.html#special-cases-for-float-and-complex https://typing.python.org/en/latest/spec/special-types.html#...