Em Java, por exemplo, a @Override
anotação não apenas fornece a verificação em tempo de compilação de uma substituição, mas também oferece um excelente código de auto-documentação.
Estou apenas procurando por documentação (embora seja um indicador para algum verificador como o pylint, isso é um bônus). Posso adicionar um comentário ou uma documentação em algum lugar, mas qual é a maneira idiomática de indicar uma substituição no Python?
Respostas:
Com base nisso e na resposta do fwc: s, criei um pacote instalável pip https://github.com/mkorpela/overrides
De tempos em tempos, acabo aqui olhando para essa pergunta. Principalmente isso ocorre depois (novamente) da mesma falha em nossa base de código: alguém esqueceu uma classe de implementação de "interface" enquanto renomeia um método na "interface".
Bem, o Python não é Java, mas o Python tem poder - e explícito é melhor do que implícito - e há casos concretos reais no mundo real em que isso poderia me ajudar.
Então, aqui está um esboço do decorador de substituições. Isso verificará se a classe fornecida como parâmetro tem o mesmo nome de método (ou algo assim) que o método que está sendo decorado.
Se você pode pensar em uma solução melhor, por favor poste aqui!
Funciona da seguinte maneira:
e se você fizer uma versão defeituosa, ocorrerá um erro de asserção durante o carregamento da classe:
fonte
overrides
poderia copiar a docstring do método substituído se o método de substituição não tiver um próprio.Aqui está uma implementação que não requer especificação do nome interface_class.
fonte
Se você desejar isso apenas para fins de documentação, poderá definir seu próprio decorador de substituição:
Na verdade, isso não passa de um colírio para os olhos, a menos que você crie a substituição (f) de uma maneira que realmente verifique a substituição.
Mas então, este é Python, por que escrevê-lo como se fosse Java?
fonte
override
decorador.Python não é Java. Obviamente, não existe algo como verificação em tempo de compilação.
Eu acho que um comentário na doutrina é suficiente. Isso permite que qualquer usuário do seu método digite
help(obj.method)
e veja que o método é uma substituição.Você também pode estender explicitamente uma interface com
class Foo(Interface)
, o que permitirá aos usuários digitarhelp(Interface.method)
para ter uma idéia da funcionalidade que seu método se destina a fornecer.fonte
@Override
Java não é documentar - é cometer um erro quando você pretende substituir um método, mas acabou definindo um novo (por exemplo, porque você digitou um nome incorretamente; em Java, isso também pode acontecer porque você usou a assinatura errada, mas isso não é um problema no Python - mas o erro de ortografia ainda é).@Override
é a documentação, além da verificação do tempo de compilação.Improvisando a ótima resposta do @mkorpela , aqui está uma versão com
verificações, nomes e objetos de erro mais precisos
Aqui está o que parece na prática:
NotImplementedError
" não implementado na classe base "resulta em
NotImplementedError
erro mais descritivopilha completa
NotImplementedError
" tipo implementado esperado "resulta em
NotImplementedError
erro mais descritivopilha completa
A grande coisa sobre a resposta @mkorpela é que a verificação acontece durante alguma fase de inicialização. A verificação não precisa ser "executada". Referindo-se aos exemplos anteriores,
class B
nunca é inicializado (B()
), aindaNotImplementedError
assim o valor aumentará. Isso significa que osoverrides
erros são detectados antes.fonte
overrides.py
. Não tenho certeza do que mais posso melhorar significativamente, exceto para alterar os tipos de exceção deTypeError
paraNotImplementedError
.types.MethodType
. Essa foi uma boa ideia na sua resposta.Como outros já disseram, diferentemente do Java, não existe a tag @Overide, mas acima você pode criar seus próprios decoradores. No entanto, sugiro usar o método global getattrib () em vez de usar o dict interno para obter algo como o seguinte:
Se você quiser, você pode pegar o getattr () em sua própria tentativa, tente aumentar o seu próprio erro, mas acho que o método getattr é melhor nesse caso.
Isso também captura todos os itens vinculados a uma classe, incluindo métodos de classe e variáveis
fonte
Baseado na ótima resposta do @ mkorpela, escrevi um pacote semelhante ( ipromise pypi github ) que faz muito mais verificações:
Suponha que
A
herdaB
eC
,B
herdaC
.O módulo ipromise verifica se:
Se
A.f
substituiB.f
,B.f
deve existir eA
deve herdar deB
. (Esta é a verificação do pacote de substituições).Você não tem o padrão
A.f
que declara que substituiB.f
, que declara que substituiC.f
.A
deve dizer que substitui a partir deC.f
poisB
pode decidir parar de substituir esse método e isso não deve resultar em atualizações posteriores.Você não tem o padrão
A.f
declara que ele substituiC.f
, masB.f
não declara sua substituição.Você não tem o padrão
A.f
que declara que substituiC.f
, masB.f
declara que substitui de algumasD.f
.Ele também possui vários recursos para marcar e verificar a implementação de um método abstrato.
fonte
O Hear é mais simples e funciona sob o Jython com classes Java:
fonte
O decorador que fiz não apenas verificou se o nome do atributo de substituição é qualquer superclasse da classe em que o atributo está sem precisar especificar uma superclasse, mas também decorou também para garantir que o atributo de substituição seja do mesmo tipo que o de substituição atributo. Os métodos de classe são tratados como métodos e os métodos estáticos são tratados como funções. Este decorador trabalha para chamadas, métodos de classe, métodos estáticos e propriedades.
Para obter o código-fonte, consulte: https://github.com/fireuser909/override
Esse decorador funciona apenas para classes que são instâncias de substituição.OverridesMeta, mas se sua classe for uma instância de uma metaclasse personalizada, use a função create_custom_overrides_meta para criar uma metaclasse compatível com o decorador de substituição. Para testes, execute o módulo override .__ init__.
fonte
No Python 2.6+ e no Python 3.2+ você pode fazê-lo (na verdade, simule , o Python não suporta sobrecarga de funções e a classe filho substitui automaticamente o método dos pais). Podemos usar decoradores para isso. Mas primeiro, observe que Python
@decorators
e Java@Annotations
são coisas totalmente diferentes. O anterior é um invólucro com código concreto, enquanto mais tarde é um sinalizador para o compilador.Para isso, primeiro faça
pip install multipledispatch
resultado:
Uma coisa a lembrar é que, como o Python não possui sobrecarga de função diretamente, mesmo que a Classe B não herda da Classe A, mas precise de todos esses
foo
s, você também precisará usar o @Override (embora o apelido 'Overload' seja parecido) melhor nesse caso)fonte