[Python-ideas] @Override decorator

Steven D'Aprano steve at pearwood.info
Tue Jul 19 07:51:04 EDT 2016


On Tue, Jul 19, 2016 at 03:18:34PM +1000, Nick Coghlan wrote:

> On 19 July 2016 at 14:04, Guido van Rossum <guido at python.org> wrote 
in response to my comments:

> > The same argument would apply against abstractmethod... 

Well, to be honest, I've never been in a situation where I either needed 
abstractmethod or knowingly had to deal with a class that used it.

Maybe I just don't use classes enough to see why this proposal is 
useful.

> > I have definitely
> > wondered when looking over some code whether it was defining or overriding a
> > method.

Isn't that one of the features of IDEs?

(Which doesn't help those who aren't using an IDE.)


> > But requiring people to always decorate overrides seems hard, unless
> > we made it a property that can be enforced by a metaclass, maybe?

[Nick] 
> This is trickier in Python than it is in Java, since we support
> multiple inheritance, and we don't require that subclasses be drop-in
> replacements for their parent class.

Indeed.


> The key difference I see between @abstractmethod and this proposal is
> that @abstractmethod is a service that base class authors provide to
> subclass authors to say "Hey, when subclassing this, you *need* to
> override these, or your subclass won't work properly". In effect, it's
> an implicit test case for all future subclass definitions.
> 
> By contrast, this proposal would go in the other direction: it would
> be an assertion by the author of a *subclass* that that particular
> method isn't new, it's inherited from a parent class, and they're
> replacing the existing implementation with a new one. It would only
> add new information for readers in cases where the method wasn't
> already calling super() (since the latter already implies you expect
> there to be at least one further implementation along the MRO to
> call).
> 
> In my view, that puts it more in the category of type annotations and
> the "missing attribute" detection in tools like pylint than it does
> abstractmethod: rather than checking it at runtime, you'd want static
> checkers like mypy to flag it as a structural error if a method
> declared as replacing a base class method wasn't actually doing so.

Certainly this is something which static checkers *could* do, but surely 
a runtime check would be sufficient? The runtime check only needs to 
occur when the class is defined, not on every call. It could look 
something like this:

def override(method):
    proxy = get_class_proxy()  # MAGIC GOES HERE
    assert hasattr(method.__name__, proxy)
    return method

I say MAGIC GOES HERE because of course the class doesn't exist yet. The 
get_class_proxy() function should return some sort of proxy to the 
soon-to-exist class' MRO.

(Maybe this is harder to write than I thought.)

Having it work at class definition time rather than compile-time means 
that it will work with odd corner cases like injected methods:

class C:
    pass

...
...
C.method = something()

class D(C):
    @override
    def method(self):
        pass


I wouldn't expect a purely static checker to necessarily realise that 
C.method exists, but there's no problem for the runtime check.


> So a "typing.override" to complement "typing.overload" would make
> sense to me, but a checked-at-runtime decorator wouldn't (doing it
> that way would also let you put the override annotation in stub files
> instead of directly in the code).



-- 
Steve


More information about the Python-ideas mailing list