Why can @decorator not decorate a staticmethod or a classmethod?
Solution 1
It works when @classmethod
and @staticmethod
are the top-most decorators:
from decorator import decorator
@decorator
def print_function_name(function, *args):
print '%s was called.' % function.func_name
return function(*args)
class My_class(object):
@classmethod
@print_function_name
def get_dir(cls):
return dir(cls)
@staticmethod
@print_function_name
def get_a():
return 'a'
Solution 2
classmethod
and staticmethod
return descriptor objects, not functions. Most decorators are not designed to accept descriptors.
Normally, then, you must apply classmethod
and staticmethod
last when using multiple decorators. And since decorators are applied in "bottom up" order, classmethod
and staticmethod
normally should be top-most in your source.
Like this:
class My_class(object):
@classmethod
@print_function_name
def get_dir(cls):
return dir(cls)
@staticmethod
@print_function_name
def get_a():
return 'a'
Solution 3
Is this what you wanted?
def print_function_name(function):
def wrapper(*args):
print('%s was called.' % function.__name__)
return function(*args)
return wrapper
class My_class(object):
@classmethod
@print_function_name
def get_dir(cls):
return dir(cls)
@staticmethod
@print_function_name
def get_a():
return 'a'
user238424
Updated on June 08, 2022Comments
-
user238424 about 2 years
Why can
decorator
not decorate a staticmethod or a classmethod?from decorator import decorator @decorator def print_function_name(function, *args): print '%s was called.' % function.func_name return function(*args) class My_class(object): @print_function_name @classmethod def get_dir(cls): return dir(cls) @print_function_name @staticmethod def get_a(): return 'a'
Both
get_dir
andget_a
result inAttributeError: <'classmethod' or 'staticmethod'>, object has no attribute '__name__'
.Why does
decorator
rely on the attribute__name__
instead of the attributefunc_name
? (Afaik all functions, including classmethods and staticmethods, have thefunc_name
attribute.)Edit: I'm using Python 2.6.
-
gahooa over 14 yearsWhy are you calling function(*args) INSIDE the decorator? It's job is to simply return a function (in your case, unmodified).
-
Admin over 14 yearsgahooa: because that's one way 'decorator' (what he imports, not the language construct) works, see pypi.python.org/pypi/decorator.
-
mykhal over 14 years@taldor you have decorator module in py 2.6 ?
-
user238424 over 14 years@mykhal: I installed it separately.
-
-
Peter Hansen over 14 yearsI'm not sure you realized, but the "decorator" package he's using does the same thing as the construct with "wrapper". The only difference between your snippets is the order of applying the decorators in My_class. You might clarify that in the answer to explain why it fixes things.
-
mykhal over 14 yearsThanks for a correction. I was playing with the problem in py3k, where the decorator module is missing. I meant my reply to be the quick one, and was sure that someone will post the better answer with detailed explanation
-
Jochen Ritzel over 14 yearsAs a rule,
classmethod
andstaticmethod
apply a special kind of magic and have to be called last. -
mykhal over 14 years@(Peter Hansen) .. however, there's no decorator module in python 2.6 either
-
Nicolas Fonteyne over 2 yearsKeep in mind that this is not 100% interchangeable. Moving the builtin decorators up may affect characteristics of the result method itself, e.g. if
print_function_name
was a decorating class, the outstanding type of the result method would be affected by the overruling builtin decorator