Tenho um código Python que tem o seguinte formato:
from dataclasses import dataclass
@dataclass
class Foo_Data:
foo: int
class Foo_Processor:
def process(self, data: Foo_Data): ...
class Foo_Loader:
def load(self, file_path: str) -> Foo_Data: ...
@dataclass
class Bar_Data:
bar: str
class Bar_Processor:
def process(self, data: Bar_Data): ...
class Bar_Loader:
def load(self, file_path: str) -> Bar_Data: ...
Tenho várias instâncias desse tipo de configuração de Dados/Processador/Carregador, e todas as classes têm as mesmas assinaturas de método módulo da família de classes específica (Foo, Bar, etc.). Existe uma maneira pythonic de formalizar esse relacionamento entre classes para impor uma estrutura semelhante se eu decidir criar uma família de classes Spam_Data
, Spam_Processor
, e Spam_Loader
? Por exemplo, quero algo para impor que Spam_Processor
tenha um process
método que receba um argumento do tipo Spam_Data
. Existe uma maneira de atingir essa padronização de alguma forma com classes abstratas, tipos genéricos ou alguma outra estrutura?
Tentei usar classes abstratas, mas o mypy corretamente aponta que ter todas as classes *_Data como subclasses de uma Data
classe abstrata e, da mesma forma, ter todas as classes *_Processor como subclasses de uma Processor
classe abstrata viola o princípio de substituição de Liskov, já que cada processador é projetado apenas para sua respectiva classe Data (ou seja, Foo_Processor
não pode processar Bar_Data
, mas seria de se esperar que pudesse se essas classes tivessem superclasses Processor
e Data
fossem compatíveis dessa forma).
Você pode usar classes base abstratas (ABCs) com Generics. Dessa forma, você pode definir uma interface comum, garantindo a segurança do tipo:
Agora você pode definir suas classes específicas
Escrever seu código dessa maneira combina os benefícios de uma interface comum com a segurança de tipos.
Os ABCs garantem que as subclasses implementem os métodos necessários, promovendo uma estrutura consistente.
Os genéricos permitem operações específicas de tipo, melhorando a legibilidade e a manutenção do código.
Como confirmação com mypy: