Estou tentando dividir minha enorme classe em duas; bem, basicamente na classe "principal" e um mixin com funções adicionais, como:
main.py
Arquivo:
import mymixin.py
class Main(object, MyMixin):
def func1(self, xxx):
...
mymixin.py
Arquivo:
class MyMixin(object):
def func2(self: Main, xxx): # <--- note the type hint
...
Agora, embora isso funcione bem, a dica de tipo MyMixin.func2
obviamente não pode funcionar. Eu não posso importar main.py
, porque eu obteria uma importação cíclica e sem a dica, meu editor (PyCharm) não poderia dizer o que self
é.
Estou usando Python 3.4, disposto a mudar para 3.5 se houver uma solução disponível lá.
Existe alguma maneira de dividir minha classe em dois arquivos e manter todas as "conexões" para que meu IDE ainda me ofereça preenchimento automático e todas as outras vantagens que vêm dele, sabendo os tipos?
self
, já que sempre será uma subclasse da classe atual (e qualquer sistema de verificação de tipo deve ser capaz de descobrir isso por conta própria). Estáfunc2
tentando ligarfunc1
, o que não está definido emMyMixin
? Talvez devesse ser (comoabstractmethod
, talvez)?class Main(MyMixin, SomeBaseClass)
para que os métodos da classe mais específica possam sobrescrever os da classe baseRespostas:
Receio que não haja uma maneira extremamente elegante de lidar com os ciclos de importação em geral. Suas opções são reprojetar seu código para remover a dependência cíclica ou, se não for viável, fazer algo assim:
A
TYPE_CHECKING
constante está sempreFalse
em tempo de execução, portanto, a importação não será avaliada, mas mypy (e outras ferramentas de verificação de tipo) avaliará o conteúdo desse bloco.Também precisamos fazer a
Main
anotação de tipo em uma string, efetivamente declarando-o, uma vez que oMain
símbolo não está disponível em tempo de execução.Se você estiver usando o Python 3.7+, podemos pelo menos pular a necessidade de fornecer uma anotação de string explícita, aproveitando o PEP 563 :
A
from __future__ import annotations
importação fará com que todas as dicas de tipo sejam strings e pulará sua avaliação. Isso pode ajudar a tornar nosso código um pouco mais ergonômico.Dito isso, usar mixins com mypy provavelmente exigirá um pouco mais de estrutura do que você tem atualmente. Mypy recomenda uma abordagem que é basicamente o que
deceze
está descrevendo - criar um ABC que tanto suaMain
quanto asMyMixin
classes herdam. Eu não ficaria surpreso se você acabasse precisando fazer algo semelhante para deixar o verificador de Pycharm feliz.fonte
typing
, mas o PyCharm também ficou muito feliz com eleif False:
.__init__
typing. TYPE_CHECKING
: python.org/dev/peps/pep-0484/#runtime-or-type-checkingPara pessoas que lutam com importações cíclicas ao importar classe apenas para verificação de tipo: você provavelmente desejará usar uma referência direta (PEP 484 - dicas de tipo):
Então, em vez de:
Você faz:
fonte
File -> Invalidate Caches
?if False:
você também podefrom typing import TYPE_CHECKING
eif TYPE_CHECKING:
.O maior problema é que, para começar, seus tipos não são sãos.
MyMixin
faz uma suposição codificada de que ele será misturado emMain
, ao passo que poderia ser misturado a qualquer número de outras classes, caso em que provavelmente seria quebrado. Se seu mixin for codificado para ser mixado em uma classe específica, você também pode escrever os métodos diretamente naquela classe em vez de separá-los.Para fazer isso corretamente com uma digitação sã,
MyMixin
deve ser codificado em uma interface ou classe abstrata na linguagem Python:fonte
Acontece que minha tentativa original também estava bem próxima da solução. Isso é o que estou usando atualmente:
Observe a
if False
instrução import within que nunca é importada (mas o IDE sabe disso de qualquer maneira) e usando aMain
classe como string porque não é conhecida em tempo de execução.fonte
Acho que a maneira perfeita deveria ser importar todas as classes e dependências em um arquivo (como
__init__.py
) e depoisfrom __init__ import *
em todos os outros arquivos.Neste caso você é
fonte
import *
, e ainda assim você pode tirar vantagem desta abordagem fácil