En Java, por ejemplo, la @Override
anotación no solo proporciona la verificación en tiempo de compilación de una anulación, sino que es un excelente código de autodocumentación.
Solo estoy buscando documentación (aunque si es un indicador para algún corrector como pylint, es una ventaja). Puedo agregar un comentario o una cadena de documentos en alguna parte, pero ¿cuál es la forma idiomática de indicar una anulación en Python?
Respuestas:
Basado en esto y en la respuesta de fwc: s, creé un paquete pip instalable https://github.com/mkorpela/overrides
De vez en cuando termino aquí mirando esta pregunta. Principalmente esto sucede después de (nuevamente) ver el mismo error en nuestra base de código: alguien ha olvidado alguna clase de implementación de "interfaz" al cambiar el nombre de un método en la "interfaz".
Bueno, Python no es Java, pero Python tiene poder, y explícito es mejor que implícito, y hay casos concretos reales en el mundo real en los que esto me habría ayudado.
Así que aquí hay un boceto de decoraciones de anulaciones. Esto verificará que la clase dada como parámetro tenga el mismo nombre de método (o algo) que el método que se está decorando.
Si puede pensar en una mejor solución, ¡publíquela aquí!
Funciona de la siguiente manera:
y si haces una versión defectuosa, generará un error de aserción durante la carga de la clase:
fuente
overrides
podría copiar la cadena de documentación del método anulado si el método de anulación no tiene uno propio.Aquí hay una implementación que no requiere la especificación del nombre de interface_class.
fuente
Si desea esto solo con fines de documentación, puede definir su propio decorador de anulación:
Esto no es más que un placer visual, a menos que cree una anulación (f) de tal manera que realmente se compruebe si hay una anulación.
Pero entonces, esto es Python, ¿por qué escribirlo como si fuera Java?
fuente
override
decorador.Python no es Java. Por supuesto, no existe tal cosa como la verificación en tiempo de compilación.
Creo que un comentario en la cadena de documentación es suficiente. Esto permite que cualquier usuario de su método escriba
help(obj.method)
y vea que el método es una anulación.También puede ampliar explícitamente una interfaz con
class Foo(Interface)
, lo que permitirá a los usuarios escribirhelp(Interface.method)
para tener una idea sobre la funcionalidad que su método está destinado a proporcionar.fuente
@Override
Java no es documentar: es detectar un error cuando pretendía anular un método, pero terminó definiendo uno nuevo (por ejemplo, porque escribió mal un nombre; en Java, también puede suceder porque usó la firma incorrecta, pero esto no es un problema en Python, pero el error de ortografía todavía lo es).@Override
documentación es además de la verificación del tiempo de compilación.Improvisando en @mkorpela gran respuesta , aquí hay una versión con
comprobaciones, nombres y objetos de error más precisos
Así es como se ve en la práctica:
NotImplementedError
" no implementado en la clase base "da como resultado un
NotImplementedError
error más descriptivocompleta pila
NotImplementedError
" tipo implementado esperado "da como resultado un
NotImplementedError
error más descriptivocompleta pila
Lo mejor de la respuesta de @mkorpela es que la verificación ocurre durante alguna fase de inicialización. La verificación no necesita ser "ejecutada". Refiriéndose a los ejemplos anteriores,
class B
nunca se inicializa (B()
), sin embargoNotImplementedError
, aún se elevará. Esto significa que losoverrides
errores se detectan antes.fuente
overrides.py
. No estoy seguro de qué más puedo mejorar significativamente, excepto para cambiar los tipos de excepción deTypeError
aNotImplementedError
.types.MethodType
. Esa fue una buena idea en tu respuesta.Como otros han dicho, a diferencia de Java, no hay una etiqueta @Overide, sin embargo, anteriormente puede crear sus propios decoradores, sin embargo, sugeriría usar el método global getattrib () en lugar de usar el dict interno para obtener algo como lo siguiente:
Si quisieras, podrías atrapar getattr () en tu propio intento, atrapar, generar tu propio error, pero creo que el método getattr es mejor en este caso.
Además, esto captura todos los elementos vinculados a una clase, incluidos los métodos de clase y las variables
fuente
Basado en la gran respuesta de @ mkorpela, he escrito un paquete similar ( ipromise pypi github ) que hace muchas más comprobaciones:
Supongamos que
A
hereda deB
yC
,B
hereda deC
.El módulo ipromise verifica que:
Si se
A.f
anulaB.f
,B.f
debe existir yA
debe heredar deB
. (Este es el cheque del paquete de anulaciones).No tiene el patrón
A.f
que declara que anulaB.f
, que luego declara que anulaC.f
.A
debería decir que se anula,C.f
ya queB
podría decidir dejar de anular este método, y eso no debería dar lugar a actualizaciones posteriores.No tiene el patrón
A.f
que declara que anulaC.f
, peroB.f
no declara su anulación.No tiene el patrón
A.f
que declara que anulaC.f
, peroB.f
declara que anula a algunosD.f
.También tiene varias características para marcar y verificar la implementación de un método abstracto.
fuente
Escuchar es más simple y funciona bajo Jython con clases Java:
fuente
El decorador que hice no solo verificó si el nombre del atributo de anulación en es una superclase de la clase en la que se encuentra el atributo sin tener que especificar una superclase, este decorador también verifica para asegurarse de que el atributo de anulación debe ser del mismo tipo que el anulado atributo. Los métodos de clase se tratan como métodos y los métodos estáticos se tratan como funciones. Este decorador funciona para invocables, métodos de clase, métodos estáticos y propiedades.
Para el código fuente, consulte: https://github.com/fireuser909/override
Este decorador solo funciona para clases que son instancias de override. OverridesMeta pero si su clase es una instancia de una metaclase personalizada, use la función create_custom_overrides_meta para crear una metaclase que sea compatible con el decorador de reemplazo. Para las pruebas, ejecute el módulo de anulación .__ init__.
fuente
En Python 2.6+ y Python 3.2+ puedes hacerlo (en realidad, simularlo , Python no admite la sobrecarga de funciones y la clase secundaria anula automáticamente el método de los padres). Podemos usar decoradores para esto. Pero primero, tenga en cuenta que Python
@decorators
y Java@Annotations
son cosas totalmente diferentes. El anterior es un contenedor con código concreto, mientras que el otro es un indicador para el compilador.Para esto, primero haz
pip install multipledispatch
salida:
Una cosa para recordar es que, dado que Python no tiene sobrecarga de funciones directamente, por lo que incluso si la Clase B no hereda de la Clase A, pero necesita todas esas
foo
mensajes, también debe usar @Override (aunque se usará el alias 'Sobrecarga' mejor en ese caso)fuente