'Python type hint for (any) class

I want to type hint the following function:

def get_obj_class(self) -> CLASS_TYPE:
  return self.o.__class__
  • CLASS_TYPE should denote classes.
  • self.o could be of any type determined at runtime.

On a similar note, if I have a function f(cls: CLASS_TYPE) which returns an instance of cls, is there a way to type hint the return value appropriately?



Solution 1:[1]

I'd recommend using a combination of TypeVar, to indicate that your self.o value could be any arbitrary type, and Type, in the following way:

from typing import TypeVar, Type

T = TypeVar('T')

class MyObj:
    def __init__(self, o: T) -> None:
        self.o = o

    def get_obj_class(self) -> Type[T]:
        return type(self.o)

def accept_int_class(x: Type[int]) -> None:
    pass

i = MyObj(3)
foo = i.get_obj_class()
accept_int_class(foo)    # Passes

s = MyObj("foo")
bar = s.get_obj_class()
accept_int_class(bar)    # Fails

If you want the type of o to be even more dynamic, you could explicitly or implicitly give it a type of Any.


Regarding your latter question, you'd do:

def f(cls: Type[T]) -> T:
    return cls()

Note that you need to be careful when instantiating your class -- I don't remember what Pycharm does here, but I do know that mypy currently does not check to make sure you're calling your __init__ function correctly/with the right number of params.

(This is because T could be anything, but there's no way to hint what the constructor ought to look like, so performing this check would end up being either impossibly or highly difficult.)

Solution 2:[2]

For Python >=3.7, use type (see also PEP 585):

def get_obj_class(self) -> type:
    return self.o.__class__

For Python <3.7, use typing.Type:

def get_obj_class(self) -> typing.Type:
    return self.o.__class__

Solution 3:[3]

What about typing.Type?

That seems to fit since __class__ should always return a type.

import typing

def test(t: object) -> typing.Type:
    return t.__class__

class Dummy(object):
    pass

test(Dummy())

To your second question: that should be a generic.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Michael0x2a
Solution 2 Mateen Ulhaq
Solution 3 Mateen Ulhaq