@Paul Becotte gets close. Here is a complete example based on his. Note his answer was missing the actual decorator, which needs special syntax to consume the 'self' parameter.
from abc import ABCMeta, abstractmethod # A base / metaclass class MyMeta(metaclass=ABCMeta): # Show that the subclass adopts __new__ from the parent def __new__(cls, *args, **data): obj = super().__new__(cls, *args, **data) obj.prop = "BOO" return obj # A decorator for subclass methods def decorate(self, func): def _wrapper_(*args, **kw): return "Wrapped: "+func(self, *args, **kw) return _wrapper_ # You can't @decorate wrap an @abstractmethod # but you can capture it's name lookup within the subclass # and emulate a decorator def __getattribute__(self, name): if name == "fun": func = getattr(type(self), "fun") return self.decorate(func) return object.__getattribute__(self, name) # An abstract method, to be later defined by a subclass @abstractmethod def fun(self, data): pass # A non-abstract method, common to all sub-classes def common(self, data): s = f"I want to live with common people...: {data}" return s # A concrete derived class class MyClass(MyMeta): # Concrete implementation def fun(self, data): s = f"Concrete can be fun: {data}" return s # Method only in MyClass def another(self, data): s = f"There are methods in this madness: {data}" return s
Lets try it (first, what happens if we forget this is a metaclass)
try: bada = MyMeta() except TypeError as er: print(er) print("Test pass - this was expected")
Now use it properly, (BTW I'm using Jupyter, so the following is in concecutive cells).
bada = MyClass() bada.fun("but take care when lifting")
bada.common("I want to do what common people do")
bada.prop
bada.another("Welcome to the house of fun()...")
_my_methodand have a non-abstract, non-overriddenmy_methodthat basically doessome_decorator(self._my_method)(*args, **kwds)?