En Python, ¿cómo indico que estoy anulando un método?
title python (7)
En Java, por ejemplo, la anotación @Override no solo proporciona la verificación en tiempo de compilación de una anulación, sino que crea un excelente código de auto-documentación. Solo estoy buscando documentación (aunque si es un indicador para algún inspector como la pildora, eso es una ventaja). Puedo agregar un comentario o un docstring en alguna parte, pero ¿cuál es la manera idiomática de indicar una anulación en Python?
Al igual que otros, a diferencia de Java, no existe la etiqueta @Overide, pero puedes crear tus propios decoradores utilizando el método getattrib () global, en lugar de utilizar el dict interno para obtener algo como lo siguiente:
def Override(superClass):
def method(func)
getattr(superClass,method.__name__)
return method
Si quisieras, podrías capturar getattr () en tu propia captura de prueba, plantea tu propio error, pero creo que el método getattr es mejor en este caso.
También esto atrapa todos los elementos vinculados a una clase, incluidos los métodos de clase y los elementos vairables
Aquí hay una implementación que no requiere la especificación del nombre de la clase interface_.
import inspect
import re
def overrides(method):
# actually can''t do this because a method is really just a function while inside a class def''n
#assert(inspect.ismethod(method))
stack = inspect.stack()
base_classes = re.search(r''class.+/((.+)/)/s*/:'', stack[2][4][0]).group(1)
# handle multiple inheritance
base_classes = [s.strip() for s in base_classes.split('','')]
if not base_classes:
raise ValueError(''overrides decorator: unable to determine base class'')
# stack[0]=overrides, stack[1]=inside class def''n, stack[2]=outside class def''n
derived_class_locals = stack[2][0].f_locals
# replace each class name in base_classes with the actual class type
for i, base_class in enumerate(base_classes):
if ''.'' not in base_class:
base_classes[i] = derived_class_locals[base_class]
else:
components = base_class.split(''.'')
# obj is either a module or a class
obj = derived_class_locals[components[0]]
for c in components[1:]:
assert(inspect.ismodule(obj) or inspect.isclass(obj))
obj = getattr(obj, c)
base_classes[i] = obj
assert( any( hasattr(cls, method.__name__) for cls in base_classes ) )
return method
Escuchar es más simple y funciona bajo Jython con clases de Java:
class MyClass(SomeJavaClass):
def __init__(self):
setattr(self, "name_of_method_to_override", __method_override__)
def __method_override__(self, some_args):
some_thing_to_do()
Hasta donde yo sé, no hay una forma especial de indicar una anulación en Python. Simplemente defina el método e incluya una docstring, como siempre.
Python no es Java. Por supuesto, no existe tal cosa como la verificación en tiempo de compilación.
Creo que un comentario en el docstring 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 extender explícitamente una interfaz con la class Foo(Interface)
, que permitirá a los usuarios escribir help(Interface.method)
para tener una idea acerca de la funcionalidad que su método pretende proporcionar.
Si desea esto solo para fines de documentación, puede definir su propio decorador de anulación:
def override(f):
return f
class MyClass (BaseClass):
@override
def method(self):
pass
Esto no es más que un caramelo para los ojos, a menos que crees una anulación (f) de tal manera que realmente se compruebe si hay una anulación.
Pero entonces, este es Python, ¿por qué escribirlo como si fuera Java?
ACTUALIZACIÓN (23.05.2015): Basado en la respuesta de this y fwc: s Creé un paquete instalable de pip https://github.com/mkorpela/overrides
De vez en cuando termino aquí mirando esta pregunta. Principalmente, esto sucede después de (una vez más) 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 lo explícito es mejor que lo implícito, y hay casos concretos reales en el mundo real donde esto me habría ayudado.
Así que aquí hay un boceto del diseñador 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 solución mejor, ¡por favor publíquela aquí!
def overrides(interface_class):
def overrider(method):
assert(method.__name__ in dir(interface_class))
return method
return overrider
Funciona de la siguiente manera:
class MySuperInterface(object):
def my_method(self):
print ''hello world!''
class ConcreteImplementer(MySuperInterface):
@overrides(MySuperInterface)
def my_method(self):
print ''hello kitty!''
y si haces una versión defectuosa, generará un error de aserción durante la carga de la clase:
class ConcreteFaultyImplementer(MySuperInterface):
@overrides(MySuperInterface)
def your_method(self):
print ''bye bye!''
>> AssertionError!!!!!!!