Разрешает ли подсказка типов Python 3.5 ковариантные возвращаемые типы?

Я хотел бы знать, поддерживает ли подсказка типа Python 3.5 (модуль typing) ковариантность возвращаемого типа, в основном для автозаполнения PyCharm.

Вот мои базовые классы для моей спортивной структуры:

class BaseLeague:
    def get_teams(self) -> List[BaseTeam]:
        ...

    ...

class BaseTeam:
    def get_captain(self) -> BasePlayer:
        ...    

    def get_players(self) -> List[BasePlayer]:
        ...

    ...

class BasePlayer:
    team = None # type: BaseTeam

    ...

(Есть много других методов, которые я упустил, например, методы BaseLeague, возвращающие объекты BaseTeam/BasePlayer/BaseLeague и т. д.)

У меня есть несколько модулей, которые параллельно подклассифицируют эти 3 класса и добавляют/переопределяют методы и атрибуты.

В hockey/models.py у меня есть:

class League(BaseLeague):
    ...

class Team(BaseTeam):
    ...

class Player(BasePlayer):
    ...

И в football/models.py у меня тоже самое:

class League(BaseLeague):
    ....

class Team(BaseTeam):
    ...

class Player(BasePlayer):
    ...

(У меня более 20 других видов спорта, таких как футбол, бейсбол и т. д.)

В PyCharm, когда я нахожусь в football.models.Team и набираю self.get_captain()., PyCharm показывает мне атрибуты для базового класса BasePlayer, но я хотел бы, чтобы он показывал мне атрибуты для подкласса football.models.Player. Похоже, это тесно связано с ковариантностью возвращаемого типа.

У меня такое чувство, что мне нужно использовать Generic и TypeVar вот так:

Player = TypeVar('Player', covariant=True)
Team = TypeVar('Team', covariant=True)
League = TypeVar('League', covariant=True)

class BaseTeam(Generic[Player, Team, League]):
    def get_players(self) -> List[Player]:
        ...

А затем в football.models я бы сделал что-то вроде:

class Team(BaseTeam[Player, Team, League]):

...где Player, Team, League являются ссылками на подклассы в том же модуле.

Но это не работает (PyCharm вообще не показывает автозаполнение), и я не уверен, что использую правильный синтаксис.

Я хотел бы, чтобы это работало, потому что мои базовые классы являются частью API моего фреймворка, и мои пользователи подклассируют их сотни раз, поэтому я хотел бы, чтобы они извлекли выгоду из автозаполнения PyCharm без необходимости переопределять каждый метод в своем собственном коде. )

Кто-нибудь знает возможно ли это?


person RexE    schedule 01.08.2016    source источник
comment
разве Union это не то, что вы ищете? docs.python.org/3/library/typing.html#typing. Союз   -  person yedpodtrzitko    schedule 23.01.2017
comment
Я знаю о Союзе, но не вижу, как он решит эту проблему.   -  person RexE    schedule 25.01.2017
comment
@RexE Я оставил ответ. Если это сработало для вас, пожалуйста, отметьте это как ответ.   -  person Nicolas Quiroz    schedule 26.03.2021


Ответы (1)


Это связано с тем, что при использовании наследования от базового класса вы не переопределяете методы из базового класса, поэтому Pycharm (и, честно говоря, любое автозаполнение IntelliSense) будет предполагать, что возврат функции остается прежним. Если вы хотите изменить автозаполнение или предложения, вам нужно будет переопределить методы и изменить только возвращаемый тип. Например:

class League(BaseLeague):
    def get_teams(self) -> List[Team]:
        return super().get_teams()
    ...

class Team(BaseTeam):
    ...

class Player(BasePlayer):

И так далее.

person Nicolas Quiroz    schedule 24.02.2021