Decorator question (how to test if decorated function is in a class)
Martin P. Hellwig
martin.hellwig at dcuktec.org
Fri Jun 19 09:04:12 EDT 2009
Hi all,
I have been trying out to wrap my mind around the advantages of
decorators and thought I found a use in one of my experiments. (see code
after my sig).
Although it works, I think it should be able to do it better.
My particular problem is that I want to remove an argument (say always
the first one) when the decorated function is called.
However if the function is defined in a class the first argument is self
and thus the second argument should be removed.
Since I like to have a more general DRY approach I want to test if the
decorated function is defined in a class or not thus knowing that the
first argument is self and must be preserved.
I tried different approaches but all didn't work and looked very
unpythonic (looking at the attributes, descriptors namespaces, id() of
the function, the first argument and the decorator itself).
So is there a way to find out if the first argument is 'self' without
making a false positive if the first argument is a class instance passed
to a function?
--
MPH
http://blog.dcuktec.com
'If consumed, best digested with added seasoning to own preference.'
code:
class Decorator(object):
"When used as Decorator(argument) returns a decorator"
def __init__(self, key):
self.key = key
def __call__(self, function):
"Return a decorator"
def decorator(*arg_tuple, **arg_dict):
"The decorator test if the arguments contain a valid key"
if arg_tuple[0] == self.key:
# This means it is a simple function, so check and strip it
arg_list = arg_tuple[1::]
return(function(*arg_list, **arg_dict))
elif arg_tuple[1] == self.key:
# This means it is a class method, check it,
# strip (but retain self)
arg_list = arg_tuple
arg_list = arg_list[0:1] + arg_list[2::]
return(function(*arg_list, **arg_dict))
else:
# The key was invalid
return('invalid')
return(decorator)
class Test(object):
@Decorator('key')
def test(self, data):
return(data)
@Decorator('key')
def function_2(self, data):
return(data)
@Decorator('key')
def function_3(self, data):
return(data)
@Decorator('key')
def test_f(data):
return(data)
# Test starts here
test_c = Test()
print(test_c.test('key', 'data'))
print(test_f('key', 'data'))
print(test_c.test('invalid', 'data'))
print(test_f('invalid', 'data'))
More information about the Python-list
mailing list