Como posso digitar uma dica de que o tipo de retorno de um método de alguma classe abstrata é alguma instância dessa classe?
Minha resposta intuitiva é que
@abstractmethod
def mymethod() -> typing.Self:
pass
deveria ser a maneira correta (como sugerido neste post , por exemplo). Mas quando agora subclassifico desta classe, o tipo de retorno é restrito ao tipo da classe filha. Qual é a maneira correta de digitar hint aqui, para que cada subclasse da classe pai seja permitida?
Código de exemplo:
from abc import ABC, abstractmethod
from typing import Self, override
import random
class DiceResult(ABC):
@abstractmethod
def reroll(self) -> Self:
pass
class NaturalTwenty(DiceResult):
@override
def reroll(self) -> DiceResult: # Type checkers report an error here
return random.choice([NaturalTwenty(), NaturalOne()])
class NaturalOne(DiceResult):
@override
def reroll(self) -> DiceResult: # Type checkers report an error here
return random.choice([NaturalTwenty(), NaturalOne()])
DiceResult.reroll
não deve usarSelf
porque...Você tem que dizer que todos eles retornam
DiceResult
, mas então você não pode usar nenhum método extra das subclasses. Vou usar um exemplo diferente porque os dados não mudam quando você os rola.Então você precisa de um protetor de tipo.
@Schwern já explica por que
typing.Self
não funciona aqui em sua resposta . Isso ocorre porquetyping.Self
sempre type hints a classe envolvente atual. Se for a subclasse de outra classe, o type hint se refere à subclasse.Para resolver isso, queremos usar a classe pai como anotação de tipo, como em
Isso não funciona na versão atual do python, pois é uma referência de avanço . A solução atual é usar uma literal de string, como em
No futuro, a primeira versão pretende funcionar também, e também já está (python >= 3.7) disponível em
__future__
. Pode ser usado como