Reputation: 27966
I want to create a decorator which is a class member, and that is going to decorate an inherited method, which is decorated.
example code:
class A(object):
__metaclass__ = ABCMeta
def __init__(self):
pass
@classmethod
def the_decorator(cls, decorated): # <-----this is what i want, with or without self/cls as an argument
def decorator()
#do stuff before
decorated()
print "decorator was called!"
#do stuff after
return decorator
@abstractmethod
def inherited():
raise NotImplemented
class B(A):
def __init__(self):
super(B,self).__init__()
#@A.the_decorator <--- this is what I want,
@overrides
#@A.the_decorator <--- or this
def inherited():
print "B.inherited was invoked"
and
b = B()
b.inherited()
should output
B.inherited was invoked
decorator was called!
Having read this guide on decorators as class members, I still haven't been able to figure out how to decorate inherited methods with decorators defined in the super class.
Note, here @overrides
is defined by the overrides
package pip install overrides
Also note i am currently using python 2.7, but would love both 2.7 and 3+ answers.
Thanks!
Upvotes: 1
Views: 73
Reputation: 139
Using Python 3, your code is just missing a few self arguments to be able to call the function with b.inherited()
class A(object):
__metaclass__ = ABCMeta
def __init__(self):
pass
@classmethod
def the_decorator(cls, decorated):
def decorator(*args, **kwargs):
#do stuff before
decorated(*args, **kwargs)
print("decorator was called!")
#do stuff after
return decorator
@abstractmethod
def inherited(self):
raise NotImplemented
class B(A):
def __init__(self):
super(B,self).__init__()
@A.the_decorator
@overrides
def inherited(self):
print("B.inherited was invoked")
Upvotes: 0
Reputation: 148965
You were not that far!
The key is that a decorator will receive one single argument which is the decorated function so it can only be a statmethod. And you also forgot that normal methods should be declared with a self
argument.
But this code should work:
class A(object):
__metaclass__ = ABCMeta
def __init__(self):
pass
@staticmethod
def the_decorator(decorated): # <-----this is what i want, with or without self/cls as an argument
def decorator(self):
#do stuff before
decorated(self)
print "decorator was called!"
#do stuff after
return decorator
@abstractmethod
def inherited():
raise NotImplemented
class B(A):
def __init__(self):
super(B,self).__init__()
@A.the_decorator #<--- this is what I want,
@overrides
#@A.the_decorator <--- or this
def inherited(self):
print "B.inherited was invoked"
I could test it under Python 2.7 except for the @overrides
decorator (I commented it in my tests)
Upvotes: 2