Reputation: 1022
I tested the following snippet with 4 common type checkers for Python and, to my surprise, none of them complained:
from typing import Any
def length(s: str) -> int:
return len(s)
def any_length(o: Any) -> int:
return length(o)
if __name__ == "__main__":
print(any_length(1234))
It's easy to predict that running this code will result in an exception:
TypeError: object of type 'int' has no len()
mypy:
Success: no issues found in 1 source file
pytype:
Success: no errors found
pyright:
0 errors, 0 warnings, 0 informations
Completed in 0.435sec
pyre:
ƛ No type errors found
I would expect at least a warning saying that Any
is not a subtype of str
and therefore application of length: str -> int
to an object of type Any
is unsafe. Is there something about these particular types that makes it difficult for type checkers to consider this simple case? The problem of determining whether a concrete type is a subtype of another doesn't seem undecidable, but maybe I'm wrong here?
Upvotes: 1
Views: 103
Reputation: 530843
Any
is not just a synonym for object
.
Any
is somewhat like both a supertype of any type, and a subtype of any type, whereas object
is a supertype of all types but only a subtype of itself. (Which is not to say that Any
is a sub- or supertype of any type, since Any
is not a type.)
Intuitively,
If a function expects a value of type Any
, it will accept anything, as if Any
were a universal supertype.
But no matter what a function expects, it will accept a value of type Any
, as if Any
were a universal subtype.
A fuller description of Any
can be found in the Summary of gradual typing in PEP 484, "The Theory of Type Hints". But the Any
type is basically what allows you to type-check code that doesn't provide hints for everything. If something has no type hint, it is assumed to have type Any
, which means there are no static restrictions on how it is used, just as you would expect from a dynamially typed language.
Specifically, as the static type of o
is Any
, it is a valid argument for the function length
which expects a str
(as Any
is consistent with str
). That doesn't mean any_length(1234)
will work at runtime, because you basically lied about the type of value any_length
requires to pass to length
.
Upvotes: 6