Вы можете заставить ваш декоратор работать, вам просто нужно сделать его дескриптором, а не функцией.Вам нужно реализовать метод __set_name__
, чтобы получить ссылку на класс, к которому вы были добавлены.С помощью ссылки на класс вы можете сделать вызов с двумя аргументами super
:
import functools
class after:
def __init__(self, method):
self.method = method
def __set_name__(self, owner, name):
self.owner = owner
self.name = name # using self.method.__name__ might be better?
def __get__(self, instance, owner):
if instance is None:
return self
return functools.partial(self, instance)
def __call__(self, instance, *args, **kwargs):
assert(self.owner is not None and self.name is not None)
getattr(super(self.owner, instance), self.name)(*args, **kwargs)
return self.method(instance, *args, **kwargs)
Вы также можете сделать before
, что будет почти таким же, только с последними двумя строками вобратный порядок (и некоторая путаница для обработки возвращаемого значения).
Я бы отметил, что этот декоратор в общем-то менее полезен, чем обычный вызов super
, поскольку вы не можете с пользой взаимодействовать сзначение, возвращаемое переопределенным методом, или измените передаваемые ему аргументы.Не существует before
или after
оформленного метода, который может копировать эти классы:
class Foo:
def foo(self, x, y):
return x + y
class Bar(Foo):
def foo(self, x, y, z):
return super().foo(x//2, y+1) * z