5

I am trying to write a decorator for an instance method, as follows:

from functools import wraps

def plus_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        return 1 + f(*args, **kwargs)
    return wrapper

@plus_decorator
def return_i(i):
    return i

class A(object):
    @plus_decorator
    def return_i(self, i):
        return i

    @plus_decorator
    @classmethod
    def return_i_class(cls, i):
        return i

    @plus_decorator
    @staticmethod
    def return_i_static(i):
        return i

if __name__ == '__main__':
    print return_i(1)
    a = A()
    print a.return_i(1)
    print A.return_i_class(1)
    print A.return_i_static(1)

However, it pops up the error:

AttributeError: 'classmethod' object has no attribute '__module__'

I am wondering why the decorator does not work on classmethod and staticmethod. I think the decorator mostly just passes all the parameters it receives to the wrapper, and only modifies the result. How can I modify the decorator to make it work for classmethod and staticmethod?

3
  • What does your callsite look like? Commented Jul 13, 2017 at 1:53
  • This works fine. You aren't creating an instance of A() to call it, e.g. a = A(); a.return_i(1). Perhaps you also need @classmethod? Commented Jul 13, 2017 at 1:54
  • Oops. The original error I met was decorator for class method, and somehow I messed up the callsite for instance method. Let me change the content. Commented Jul 13, 2017 at 1:59

2 Answers 2

9

Just flip the order. Put the @classmethod or @staticmethod on the outside, and your decorator (which uses @wraps, and therefore needs a bare function) on the inside.

@classmethod
@plus_decorator
def return_i_class(cls, i):
    return i
Sign up to request clarification or add additional context in comments.

Comments

3

Try reversing.

It will work when @staticmethod and @classmethod are top-most decorators as explained here

Because your decorator expects a function but both the other decorators return descriptor objects.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.