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 -- https://mail.python.org/mailman/listinfo/python-list