I was wondering why Python's typing module does not support isinstance(<obj>, Any) and raises a TypeError. I would expect it to always return True. Is there a specific reason why it does not always return True?
>>> from typing import Any
>>> isinstance(1, Any)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/peter/miniconda3/envs/prefect_utils/lib/python3.9/typing.py", line 338, in __instancecheck__
raise TypeError(f"{self} cannot be used with isinstance()")
TypeError: typing.Any cannot be used with isinstance()
The Any class docstring seems to state the reason:
"""Special type indicating an unconstrained type.
- Any is compatible with every type.
- Any assumed to have all methods.
- All values assumed to be instances of Any.
Note that all the above statements are true from the point of view of
static type checkers. At runtime, Any should not be used with instance
or class checks.
"""
def __instancecheck__(self, obj):
raise TypeError("Any cannot be used with isinstance().")
def __subclasscheck__(self, cls):
raise TypeError("Any cannot be used with issubclass().")
It's likely that treating these objects as an actual instance or subclass may lead to problems if they don't provide exactly what the instance or subclass should. Instead, they "fake" the fact they can be anything but not so much as to cause damage by being treated that way in the type hierarchy.
Most things in typing are not intended for runtime type checking. Most types cannot be sensibly checked dynamically, so typing avoids pretending it's possible.
The Any type is not a proper type – it is compatible with any type in any usage. Depending on the use, it can be both the super and sub type of another type.
Most prominently, Any supports all operations. Therefore, isinstance(x, Any) == True would mean that x supports all operations, regardless of x' concrete type. This is not sensible for most proper types.
Consider for example checking an integer as an "instance of Any", which implies it supports slicing:
x = 3
if isinstance(x, Any): # x supports any operation in this block
print(x[:3]) # slicing is part of "all operations"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With