2

How to do python typing for list of classes.

Suppose I have following classes.

from dataclasses import dataclass

@dataclass
class A:
    name: str

@dataclass
class B:
   age: int

#...
CLASSES = [A, B]  #... more classes in list

Now I define a function that instantiate any one of the following class

def func(resource: Union[*CLASSES], value: Union[str, int]):
    return resource(value)

But type-hinting is not valid here. How to do type hinting from List?

12
  • 2
    What do you mean by "type casting", exactly? Please be specific. Note, "type casting" is not really a term that is applicable to python, although it is used informall to mean "type conversion". Commented Dec 7, 2020 at 6:58
  • 2
    If you have 10 or more possibly classes, there's already something seriously wrong with your code - it's likely they share a super-class that would be a better match; at any rate, you can't use expansion on a variable to get at the types that are stored in it to define the type of function parameters - you're mixing runtime and compile-time information Commented Dec 7, 2020 at 6:59
  • 2
    Type hints must be static so that the linters can validate them. Commented Dec 7, 2020 at 7:02
  • 2
    No, type hints are only for the IDE/linter to make it easier to spot bugs. They are not used by the interpreter (at least not by CPython). You don't have to use a Union; you can use what @Grismar suggested in their answer. Unions are only necessary if you are using built-in or third party classes that you can't modify. Commented Dec 7, 2020 at 7:05
  • 1
    Does this answer your question? Python typing: Dynamically Create Literal Alias from List of Valid Values Commented Dec 14, 2020 at 12:12

1 Answer 1

2

This achieves what you want using a super-class that all the intended classes share:

from typing import Union
from dataclasses import dataclass


@dataclass
class MyDataMixin:
    pass


@dataclass
class A(MyDataMixin):
    name: str


@dataclass
class B(MyDataMixin):
    age: int


def func(resource: MyDataMixin, value: Union[str, int]):
    return resource

You can't use expansion in the type definition of the parameter like you were trying to do, that only works on variables at runtime.

As @Selcuk indicated in the comments, naming it MyDataMixin makes more sense, as the class is not intended to be used by itself. You could go further and ensure it's just an abstract class - but that's beyond the scope of the question.

Sign up to request clarification or add additional context in comments.

3 Comments

Better name it a Mixin so that other (actual) superclasses can be extended if needed.
Shall I use ABC instead of dataclass as Parent?
Yeah, the mixin doesn't have to be a dataclass itself, although it certainly can be. I wouldn't go the route of using ABC unless you have specific reasons to want to use an abstract base class, like requiring an abstract method to be implemented on each subclass - but that goes way beyond what you were asking. Just inheriting from a shared base class is enough. Everything else is a different matter.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.