@glukonator

Как указать тайпхинт для возврата наследников?

Привет

from abc import ABC
from random import choice
from typing import TypeVar

T = TypeVar('T', bound='AbstractCls')


class AbstractCls(ABC):
    @classmethod
    def get_cls(cls) -> type[T]:
        return choice(cls.__subclasses__())

    def m(self):
        pass


class A(AbstractCls):
    def m_a(self):
        pass

    # @classmethod
    # def get_cls(cls) -> type['A']:
    #     return super().get_cls()


class B(AbstractCls):
    pass


cls = AbstractCls.get_cls()
o = cls()


получая такое PyCharm выдает (Ctrl-Q) для cls и o:
cls: Type[T] = AbstractCls.get_cls()
o: Any = cls()


python 3.10

Из-за потери связи не работает автодополнение:
IDE не знает про AbstractCls.m() => не дает подсказок по аргументам, документации и т.д.

1) Можно это как-то пофиксить, чтобы работало будто указано
class AbstractCls(ABC):
    @classmethod
    def get_cls(cls) -> type['AbstractCls']:
...
cls: Type[AbstractCls] = AbstractCls.get_cls()
o: AbstractCls = cls()

?

2) Можно ли сделать так, чтобы подсказки вылезали и по методам класса А? Само собой если я укажу
cls = A.get_cls()
Автоматически без переопределения в самом классе ( поведение возникает, если get_cls() в нем раскомментирован)

З.Ы.
  • choice просто для примера, по факту там возврат определенного класса по условиям
  • реальный код содержит немного больше наследования, но в целом пример считаю похожим.
  • Вопрос задан
  • 73 просмотра
Решения вопроса 1
petushok55
@petushok55
Обучаюсь на практике.
1) Чтобы исправить проблему с автодополнением, можно указать тип переменной `cls` как `Type[AbstractCls]`, чтобы IDE знала, что она является экземпляром класса `AbstractCls`. Это можно сделать следующим образом:

cls: Type[AbstractCls] = AbstractCls.get_cls()

Теперь IDE будет корректно подсказывать методы и атрибуты класса `AbstractCls`.

2) К сожалению, автоматические подсказки для методов класса `A` не будут появляться без переопределения `get_cls()` в самом классе `A`. Это связано с тем, что статические методы и методы класса не наследуются от родительского класса, и IDE не сможет автоматически определить, какие методы доступны для экземпляров класса `A`. Поэтому, чтобы иметь автодополнение для методов класса `A`, необходимо переопределить `get_cls()` в классе `A`, как вы уже указали в комментарии в коде.

@classmethod
def get_cls(cls) -> Type['A']:
    return super().get_cls()


Теперь IDE будет предоставлять автодополнение для методов класса `A` при использовании переменной `o`.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы