As far as I know, Python is a gradual typing language. And all unannotated variables are of type Any
which is a supertype and subtype of any type. Why then is the following code rejected by the static type checker?
def doubles(x: str) -> str:
return x + x
y = True
doubles(y)
I understand that the program is obviously incorrect, but how did the type checker guess? Shouldn't the following happen:
y
is not annotated, therefore it is of type Any- cast
Any
tostr
- accept the program
The expected behavior occurs only if you explicitly specify the Any
type. I would assume that without explicitly specifying Any
, y
would be assigned the type of the right expression, that is, bool
, but then we would not be able to change the value of y
to 123
type int
, which is not true
The static type checking system will also "look into" actually assigned values in the source code. And will, in fact, adopt the type of assigned values to un-annotated variables.
In your example, it "sees" just as we can do,
y
contains abool
. And even ify
would be annotated as beingbool | str
, it would see the actual contained value in this case is a bool. (But it actually complains about the broader type).Moreover, it won't allow simply "more broad" values to fit into narrower annotated calls: even if you do annotate
y
as "any", fetch its value at runtime from somewhere the static typing system can't "see", it will could warn you with such a call:doubles
requires astr
parameter (but it actually allows it, at least mypy).