开发者

Why can @decorator not decorate a staticmethod or a classmethod?

开发者 https://www.devze.com 2022-12-15 18:15 出处:网络
Why can decorator not decorate a staticmethod or a classmethod? from decorator import decorator @decorator

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 and get_a result in AttributeError: <'classmethod' or 'staticmethod'>, object has no attribute '__name__'.

Why does 开发者_开发问答decorator rely on the attribute __name__ instead of the attribute func_name? (Afaik all functions, including classmethods and staticmethods, have the func_name attribute.)

Edit: I'm using Python 2.6.


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'


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'


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'
0

精彩评论

暂无评论...
验证码 换一张
取 消