Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Python 3.5 type hinting allow covariant return types?

I would like to know if Python 3.5 type hinting (the typing module) supports return type covariance, mainly for PyCharm's autocompletion.

Here are my base classes for my sports framework:

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

    ...

(There are many more methods I left out, like methods on BaseLeague returning BaseTeam/BasePlayer/BaseLeague objects, etc.)

I have multiple modules that subclass these 3 classes in parallel, and add/override methods and attributes.

In hockey/models.py, I have:

class League(BaseLeague):
    ...

class Team(BaseTeam):
    ...

class Player(BasePlayer):
    ...

And in football/models.py, I have the same thing:

class League(BaseLeague):
    ....

class Team(BaseTeam):
    ...

class Player(BasePlayer):
    ...

(I have 20+ other sports, like soccer, baseball, etc..)

In PyCharm, when I'm in football.models.Team and type self.get_captain()., PyCharm shows me the attributes for the base class BasePlayer, but I would like it to show me the attributes for the subclass football.models.Player. This seems closely related to return type covariance.

I have a feeling I need to use Generic and TypeVar like this:

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]:
        ...

And then in football.models I would do something like:

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

...where Player, Team, League are references to the subclasses in the same module.

But it's not working (PyCharm is not showing any autocomplete at all), and I'm not sure if I'm using the right syntax.

I would like to get this working because my base classes are part of my framework's API, and my users subclass them hundreds of times, so I'd like them to benefit from PyCharm autocomplete, without having to override each method in their own code.)

Does anyone know if this is possible?

like image 905
RexE Avatar asked Aug 01 '16 12:08

RexE


1 Answers

That is because when using inheritance from the base class, you are not re-defining the methods from the base class, so Pycharm (and any intellisense autocompletion honestly) will assume that the return of the function remains the same. If you would like the autocompletion or suggestions to change, you would then have the re-define the methods, and only changing the return type. For example:

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

class Team(BaseTeam):
    ...

class Player(BasePlayer):

And so on.

like image 121
Nicolas Quiroz Avatar answered Oct 30 '22 19:10

Nicolas Quiroz