Reputation: 2115
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
has the same args, but __call__
also has self
for the first arg. In the wrap_me
decorator I need an access for the function being wrapped args.
Upvotes: 4
Views: 613
Reputation: 65811
This may be pretty dumb, but might as well work for the simplest case:
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
Upvotes: 0
Reputation: 7852
Unfortunately, at the time of definition (the class block in this case), the code cannot tell how a function will be used except by naming convention. Modifying 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, simple_function
is implementing a function taking a target and two parameters, an instance method taking two parameters, a class method taking two parameters, and a static method taking a target and two parameters. But these uses are not bound until after the function is defined. Both staticmethod
and classmethod
return a different object type, so you can tell those apart, if need be.
If you did want to use convention, you could inspect the function's first argument name 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
Upvotes: 2
Reputation: 123722
def wrap_me(*args):
a1, a2 = args if len(args) == 2 else args[1:]
...
Of course, you will need to modify the returned function to take the self
argument if wrap_me
was called on a class method as well.
By the way, assuming you're not actually using self
inside the function which you're decorating, it should really be a static method.
Upvotes: 0