In Python, how do I indicate I'm overriding a method? In Python, how do I indicate I'm overriding a method? python python

In Python, how do I indicate I'm overriding a method?


Based on this and fwc:s answer I created a pip installable package https://github.com/mkorpela/overrides

From time to time I end up here looking at this question.Mainly this happens after (again) seeing the same bug in our code base: Someone has forgotten some "interface" implementing class while renaming a method in the "interface"..

Well Python ain't Java but Python has power -- and explicit is better than implicit -- and there are real concrete cases in the real world where this thing would have helped me.

So here is a sketch of overrides decorator. This will check that the class given as a parameter has the same method (or something) name as the method being decorated.

If you can think of a better solution please post it here!

def overrides(interface_class):    def overrider(method):        assert(method.__name__ in dir(interface_class))        return method    return overrider

It works as follows:

class MySuperInterface(object):    def my_method(self):        print 'hello world!'class ConcreteImplementer(MySuperInterface):    @overrides(MySuperInterface)    def my_method(self):        print 'hello kitty!'

and if you do a faulty version it will raise an assertion error during class loading:

class ConcreteFaultyImplementer(MySuperInterface):    @overrides(MySuperInterface)    def your_method(self):        print 'bye bye!'>> AssertionError!!!!!!!


Here's an implementation that doesn't require specification of the interface_class name.

import inspectimport redef 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


If you want this for documentation purposes only, you can define your own override decorator:

def override(f):    return fclass MyClass (BaseClass):    @override    def method(self):        pass

This is really nothing but eye-candy, unless you create override(f) in such a way that is actually checks for an override.

But then, this is Python, why write it like it was Java?