Search code examples
pythonpython-3.xmypypython-typing

How to write the signature of isinstance (with type narrowing)


for some performance reasons I have reimplemented the isinstance builtin function with slight modifications that works faster under my constraints. Now I'm trying to make mypy happy with my function by adding a propper signature. What should be the signature of the isinstance function?

I found a way to do the simple case, where the second argument is a type.

T = TypeVar("T")

def constrained_isinstance(obj: Any, cls: Type[T]) -> TypeGuard[T]:
    pass  # let's not bother about implementation

However, I can't find a way to write a signature for tuple of types case (ex: isinstance(pet, (Dog, Cat))). I thought about using TypeVarTuple; the closest I got from a solution is this signature:

T = TypeVarTuple("T")

def constrained_isinstance(obj: Any, types: tuple[*T]) -> TypeGuard[Union[*T]]:
    pass

This is a wrong solution because narrowed types would be Union[Type[Cat], Type[Dog]] instead of Union[Cat, Dog]

There might be a way to explicit types of several elements like Types[*T] but I couldn't find it.

PS: A workaround would be to write this in the stub file:

constrained_isinstance = isinstance

But I would love to find a more beautiful way.

Thank you for your answers.


Solution

  • I found a better solution by using class.__instancecheck__, which allow me to use my modified version while calling builtin isinstance.