PEP 526 - var annotations and the spirit of python
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Jul 5 05:59:55 EDT 2018
On Thu, 05 Jul 2018 17:34:55 +1200, Gregory Ewing wrote:
> Steven D'Aprano wrote:
>
>> but the type checker should infer that if you assign None to a variable
>> which is declared int, you must have meant Optional[int] rather than
>> just int.
>
> This seems to be equivalent to saying that *all* types are Optional, in
> which case what point is there in having Optional at all?
How do you reason that?
x = 3
infers that x is an int, and only an int, not an optional int. An
explicit hint, like:
def func(x:int) -> something
requires func(x) to only accept int arguments, not int-or-None. But:
def func(x:int = None) -> something
says to the type checker, in effect, "Yeah, I know I said an int, but I
obviously also want to allow None because that's the default, so just
deal with it, okay?"
You may or may not like the "Do What I Mean" aspect of this, you might
question whether Optional[int] is really more common than Union[int, str]
(for example). But I don't see how you go from this narrowly defined
exceptional situation ("use a hint for one type and assign None on the
same line") and conclude that "all types are optional".
>> Indeed, that's often the best way, except for the redundant type hint,
>> which makes you That Guy:
>>
>> x: int = 0 # set x to the int 0
>
> But you've shown in an earlier example that such a hint is *not* always
> redundant
But it is redundant in *that* example. Your hint is not giving any more
information that what the reader, or type checker, can already infer.
These are useful:
x: Any = 3 # x can be anything, but is currently an int
x: int = None # x can be an int, or None
x: Union[int, str] = 'abc' # x can be either an int, or a
# string, not just the string you see here
but this is redundant (unless you're forced to use a type-checker with no
type inference at all):
x: int = 3
Well duh of course its an int. That's what 3 is. An int. If it were a
comment, you'd slap the writer around the head with a clue-stick:
x = 3 # x is an int
> e.g.
>
> x = 0
> x = 2.5
>
> is legal and useful,
Of course it is useful -- well, not *literally* that pair of lines, but I
know what you mean -- but its probably an error.
Mypy allows ints wherever a float is expected:
x = 0.0 # infer x is a float
x = 1 # ints are compatible with floats
https://github.com/python/typing/issues/48
which probably isn't *strictly* valid (ints can exceed the range of
floats), so I assume there's a switch to disable it. But the other way is
an error:
x = 0 # infer x is an int
x = 2.5 # that's not an int!
Some type checkers may even enforce a strict separation of ints and
floats. In any case, if you want to overrule the type checker, you can:
x: Union[int, float] = 0
x = 2.5
A better example would be:
x = 0 # infers type int, or maybe type Number
x = "foo" # certainly not a number, so a type error
> whereas
>
> x: int = 0
> x = 2.5
>
> ought to be a type error.
It ought to be a type error even without the hint.
--
Steven D'Aprano
"Ever since I learned about confirmation bias, I've been seeing
it everywhere." -- Jon Ronson
More information about the Python-list
mailing list