How can I implement a custom constructor (class method) that is inheritable in python?
The following minimized example might give an idea:
from dataclasses import dataclass
from typing import Type, TypeVar
T = TypeVar("T")
@dataclass
class Parent:
    something: int = 2
    @classmethod
    def from_float(cls: Type[T], something_as_float: float) -> T:
        return Type[T](something=int(something_as_float))
@dataclass
class Child(Parent):
    """ Should also be constructible via from_float
    """
assert isinstance(Parent.from_float(1.0), Parent)
assert isinstance(Child.from_float(1.0), Child)
mypy does not like the constructor I call when returning from from_float. I don’t know how to refer to class (Parent or Child) from the class method.
Advertisement
Answer
Pass the bound argument to TypeVar to specify that the type is a subclass of Parent. This lets mypy know that the type has the something attribute
When you create the instance use cls not Type[T]
from dataclasses import dataclass
from typing import Type, TypeVar
T = TypeVar("T", bound='Parent')
@dataclass
class Parent:
    something: int = 2
    @classmethod
    def from_float(cls: Type[T], something_as_float: float) -> T:
        return cls(something=int(something_as_float))
@dataclass
class Child(Parent):
    pass
assert isinstance(Parent.from_float(1.0), Parent)
assert isinstance(Child.from_float(1.0), Child)