Let's say I want to extend the following Python class, which includes a decorator that I don't know much about:
from somewhere import some_decorator
class One(object):
@some_decorator
def some_method(self):
do_something()
Should I decorate the overridden method or not? In other words, can I safely do:
class Two(One):
def some_method(self):
super(Two, self).some_method()
Or do I need to do:
class Two(One):
@some_decorator
def some_method(self):
super(Two, self).some_method()
Runtime Override Checks in Python Today, there is an Overrides library that provides decorators @overrides (sic) and @final and will enforce them at runtime.
In Python method overriding occurs by simply defining in the child class a method with the same name of a method in the parent class. When you define a method in the object you make this latter able to satisfy that method call, so the implementations of its ancestors do not come in play.
Overriding a method in the same class is not allowed. So, you need to do that in the child class by implementing the Inheritance concept. If you want to override the Parent Class method, create a function in the Child with the same name and number of parameters. This is called function overriding in Python.
A decorator in Python is a function that takes another function as its argument, and returns yet another function . Decorators can be extremely useful as they allow the extension of an existing function, without any modification to the original function source code.
Remember what the @decorator
syntax does:
@decorator
def foo():
print "foo"
is just syntactic sugar for
def foo():
print "foo"
foo = decorator(foo)
Thus, the undecorated function is no longer callable by its name after it has been decorated because its name has been assigned to something else.
This means that when you call super(Two, self).some_method()
in the child class, then the decorated function some_method
in the parent will be called.
Knowing whether or not you also need to decorate the child overridden method entirely depends on what you want to do and what the decorator does. But know that if you call super(Two, self).some_method()
, then you will call the decorated function.
For those wondering about edge cases, here is an example:
import functools
def print_hi(func):
"""Decorate a function to print stuff."""
@functools.wraps(func)
def wrapper_print_hi(*args, **kwargs):
print(f"hello and up next: calling {func.__qualname__}")
return func(*args, **kwargs)
return wrapper_print_hi
class Foo:
@print_hi
def gets_overridden(self) -> None:
print(f"Foo.gets_overridden")
class DFooNoRedecorate(Foo):
def gets_overridden(self) -> None:
"""Overridden but didn't re-decorate."""
print(f"{self.__class__.__name__}.gets_overridden")
class DFooRedecorate(Foo):
@print_hi
def gets_overridden(self) -> None:
"""Overridden and re-decorated."""
print(f"{self.__class__.__name__}.gets_overridden")
class DFooNoRedecorateWithSuperCall(Foo):
def gets_overridden(self) -> None:
"""Overridden but didn't re-decorate, with super call."""
super().gets_overridden()
print(f"{self.__class__.__name__}.gets_overridden")
class DFooRedecorateWithSuperCall(Foo):
@print_hi
def gets_overridden(self) -> None:
"""Overridden and re-decorated, with super call."""
super().gets_overridden()
print(f"{self.__class__.__name__}.gets_overridden")
if __name__ == "__main__":
print("---")
# Decorator doesn't happen when not explicitly called out in subclass
DFooNoRedecorate().gets_overridden()
print("---")
# Decorator does happen when explicitly called out in subclass
DFooRedecorate().gets_overridden()
print("---")
# Decorator happens during super call
DFooNoRedecorateWithSuperCall().gets_overridden()
print("---")
# Decorator happens twice: from explicit call out and during super call
DFooRedecorateWithSuperCall().gets_overridden()
print("---")
Printed output:
---
DFooNoRedecorate.gets_overridden
---
hello and up next: calling DFooRedecorate.gets_overridden
DFooRedecorate.gets_overridden
---
hello and up next: calling Foo.gets_overridden
Foo.gets_overridden
DFooNoRedecorateWithSuperCall.gets_overridden
---
hello and up next: calling DFooRedecorateWithSuperCall.gets_overridden
hello and up next: calling Foo.gets_overridden
Foo.gets_overridden
DFooRedecorateWithSuperCall.gets_overridden
---
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With