Тип базового класса в миксинах

У меня есть большой класс разбитый на миксины:

class MyObject(MyObjectFilesMixin, MyObjectProcessingMixin, ...):
    def __init__(self, value):
        self.value = self.preprocess(value)

Миксины такие:

class MyObjectFilesMixin:
    def load_from_file(cls, filename):
        return ...

Сейчас хочу добавить везде типизацию:

class MyObjectFilesMixin:
    def load_from_file(cls, filename: str) -> MyObject:
        return ...


class MyObjectProcessingMixin:
    def preprocess(self: MyObject, value: bytes):
        return value  # логика опущена

    def append(self: MyObject, other: MyObject):
        self.value += other.value

Но это приводит к циклическим зависимостям. Конечно, можно создать какой-нибудь класс вида MyObjectBase (следуя принципу инверсии зависимостей), чтобы главный класс MyObject мог наследовать этот базовый, а миксины использовали его как тип аргумента/результата в методах, но это всё же корявый тип будет. Как это можно исправить??

Немного скучаю по заголовочным/исходным файлам C++


Ответы (2 шт):

Автор решения: inzem77

у cls и self type hints не используют, так как и так понятно, что self это экземпляр объекта того класса, который вызывается, а cls это объект класса в котором определен метод данного класса(только не забудьте декоратор @classmethod)

→ Ссылка
Автор решения: AivanF.

Нашёл способ, как обойтись без дублирования кода, протоколов и т.п, DRY! Решение у меня простое:

from typing import TYPE_CHECKING, Type
if TYPE_CHECKING:
    from my_object import MyObject
MO = Type('MyObject')


class MyObjectFilesMixin:
    def load_from_file(cls: MO, filename: str) -> 'MyObject':
        # Now I'm able to access all the methods of MyObject by cls
        # with correct IDE support and MyPy checking
        return ...


class MyObjectProcessingMixin:
    def preprocess(self: 'MyObject', value: bytes):
        return value  # логика опущена

    def append(self: 'MyObject', other: 'MyObject'):
        self.value += other.value

Разве что теперь всплывает warning, видимо MyPy не ожидает получить ребёнка как тип у родителя:

Mypy: The erased type of self "Type[... MyObject]" is not a supertype of its class "Type[...MyObjectFilesMixin]"

Но это малая цена за то, чтобы методы и типы были видны и правильно поняты IDE и MyPy!

→ Ссылка