Python: decorate __call__ and normal function with the same decorator?
Is it possible in Python 2.6-2.7 to use the same decorator for the following task:
class ComplextCallableObject(object):
@wrap_me
def __call__(self, a1, a2):
pass
@wrap_me
def simple_function(a1, a2):
pass
Both ComplextCallableObject.__call__
and simple_function
have the same arguments, but __call__
also has one self
for the first arg. In the decorator, wrap_me
I need access for the wrapped args functions.
source to share
Unfortunately, at the time of definition (a class block in this case), the code cannot determine how the function will be used other than by naming convention. Modify your example a bit:
class ComplextCallableObject(object):
@wrap_me
def __call__(self, a1, a2):
pass #...
@wrap_me
def simple_function(tgt, a1, a2):
pass
ComplextCallableObject.anInstanceMethod = simple_function
ComplextCallableObject.anClassMethod = classmethod(simple_function)
ComplextCallableObject.aStaticMethod = staticmethod(simple_function)
In this case, it simple_function
implements a function that takes a target and two parameters, an instance method that takes two parameters, a class method that takes two parameters, and a static method that takes a target and two parameters. But this usage is not related only after the function is defined. Both staticmethod
and classmethod
return a different type of object, so you can talk about it if needed.
If you want to use a convention, you can check the name of the first argument to the function to see if it is self
:
def wrap_me(fn):
names = fn.func_code.co_varnames
if names and names[0]=='self':
print 'looks like an instance method'
else: print 'looks like a function'
return fn
source to share
def wrap_me(*args):
a1, a2 = args if len(args) == 2 else args[1:]
...
Of course, you will need to modify the return function to accept an argument self
if wrap_me
called in a class method as well.
By the way, if you are not using self
inside the function you are decorating, it really should be a static method.
source to share
This can be pretty silly, but it can work in the simplest case too:
In [1]: def wrap_me(func):
...: def wrapped(*args):
...: print 'arg1 is', args[-2]
...: print 'arg2 is', args[-1]
...: func(*args)
...: return wrapped
...:
In [2]: class ComplexCallableObject(object):
...: @wrap_me
...: def __call__(self, a1, a2):
...: print 'class object called'
...:
In [3]: @wrap_me
...: def simple_function(a1, a2):
...: print 'function called'
...:
In [4]: simple_function('A', 'B')
arg1 is A
arg2 is B
function called
In [5]: o = ComplexCallableObject()
In [6]: o('A', 'B')
arg1 is A
arg2 is B
class object called
source to share