Getting the generic arguments of a subclass

Question:

I have a generic base class and I want to be able to inspect the provided type for it. My approach was using typing.get_args which works like so:

from typing import Generic, Tuple, TypeVarTuple, get_args

T = TypeVarTuple("T")


class Base(Generic[*T]):
    values: Tuple[*T]


Example = Base[int, str]
print(get_args(Example)) # (<class 'int'>, <class 'str'>)

But when I’m inheriting the class, I’m getting an empty list of parameters like so:

class Example2(Base[int, str]):
    pass


print(get_args(Example2)) # ()

What I actually need is to know what types are expected for the values property. I might have the wrong approach but I’ve also tried to use typing.get_type_hints which seems to just return Tuple[*T] as the type.

So how can I get the typed parameters?

Edit: I need to know the types of the class, not the object.

Asked By: yotamN

||

Answers:

You can also use the python function

help(package.class)

to retrieve documentation on the class. This doesn’t directly return all possible arguments but all possible arguments should be listed in the return.

This will give you the arguments available, unless it a requirement to retrieve just the arguments to plug in to something else, in which case this may not be what you are looking for.

Answered By: Tyler Davis

Use get_args with __orig_bases__:

print(get_args(Example2.__orig_bases__[0]))  # prints "(<class 'int'>, <class 'str'>)"

For convenience, you can store the generic type parameters in the __init_subclass__ hook:

from typing import Generic, TypeVarTuple, get_args

T = TypeVarTuple("T")


class Base(Generic[*T]):
    values: tuple[*T]
    type_T: tuple[type, ...]

    def __init_subclass__(cls) -> None:
        cls.type_T = get_args(cls.__orig_bases__[0])  # type: ignore


class Example2(Base[int, str]):
    pass


print(Example2.type_T)  # prints "(<class 'int'>, <class 'str'>)"
Answered By: Paweł Rubin