Search code examples
pythonmethodsdecoratorclass-method

Is it neccessary to decorate a classmethod at it's definition?


There are three kinds of methods in Python's OOP concept — instance method, class method, and static method.

class MyClass:
    def instancemethod(self):
        return 'instance method called'

    @classmethod
    def classmethod(cls):
        return 'class method called'

    @staticmethod
    def staticmethod():
        return 'static method called'

It is obvious to know all three methods. Now I create a new method in a class:

class Test():
    def ppr():
        print('what method is ppr?')

It is not instance method.

inst = Test()
inst.ppr()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ppr() takes 0 positional arguments but 1 was given

So it is a class method?

Test.ppr()
what method is ppr?

No @classmethod keyword to decorate the ppr function.


Solution

  • Lets test it out:

    class MyClass:
        def instancemethod(self):
            return 'instance method called'
    
        @classmethod
        def classmethod(cls):
            return 'class method called'
    
        @staticmethod
        def staticmethod():
            return 'static method called'
    
    class Test():
        def ppr():
            print('what method is ppr?')
    
    print(type(MyClass.instancemethod)) # -> function
    print(type(MyClass.classmethod))    # -> method
    print(type(MyClass.staticmethod))   # -> function 
    
    print(type(Test.ppr))               # -> function 
    

    As Test.ppr comes back as a function and it can be run without creating an instance - it is a @staticmethod.

    If it was a @classmethod instead - it would come back as type method.

    q.e.d.


    My IDE shows me a warning: 'Method ppr has no argument.' which hints that you probably should either add a self or a cls and the corresponding @classmethod to it.

    To answer your question - it seems it is not needed (at this point in time) - BUT it is prudent to declare them @staticmethod to make your intent clear.