Python's @classmethod and @staticmethod Explained

3 min read

For beginners who are learning object-oriented programming in Python, it is very essential to have a good grasp over class method and static method for writing more optimized and reusable code.

Also, it is very common for even experienced programmers coming from different languages to get confused between these two.

In this article, we will develop a better understanding of the class method and static methods in Python.

Static Method in Python

A @staticmethod is a method that knows nothing about the class or instance it was called on unless explicitly given. It just gets the arguments that were passed, no implicit first argument and It’s definition is immutable via inheritance.

In simpler words a @staticmethod  is nothing more than a regular function defined inside a class that doesn't have access to the instance therefore It is callable without instantiating the class.

Syntax:

class ClassName:
    @staticmethod
    def method_name(arg1, arg2, ...): ...

We use the @staticmethod decorator for defining a static method in Python, here you can observe that the static method is not taking self as an argument for the method.

Now let's look at an example.

class Myclass():
    @staticmethod
    def staticmethod():
        print('static method called')

As we discussed we can access the static method of a class without creating an object.

Myclass.staticmethod()

Output:

static method called

Although calling the method from a class instance is also possible.

my_obj = Myclass()
my_obj.staticmethod()

Output:

static method called

Great, but when are static methods useful?

The static method helps in achieving encapsulation in Python class since it is not aware of the state of the current instance. Also, static methods make code more readable and reusable and more convenient to import versus module-level functions since each method does not have to be specially imported.

class Person():
    @staticmethod
    def is_adult(age):
        if age > 18:
            return True
        else:
            return False

In the above example, we can check if the person is an adult with or without initiating the class.

Person.is_adult(23)

Output:

True

Class Method in Python

A @classmethod is a method that receives the class as the implicit first argument, just like an instance method receives the instance. This means you can use the class and its properties inside that method rather than a particular instance.

So @classmethod is basically a method of a class having access to every attribute of the class it was called on. Therefore a class method is a method that is bound to the class and not the object of the class.

Syntax:

class Class:
    @classmethod
    def method(cls, arg1, arg2, ...): ... 

The @classmethod decorator is used for creating a class methods and cls should be the first argument of every class method.

class MyClass:
    @classmethod
    def classmethod(cls):
        print('Class method called')

@classmethod functions are also callable without instantiating the class, but its definition follows Subclass, not Parent class, via inheritance.

MyClass.classmethod()

Output:

Class method called

So when to use class methods?

@classmethod are for when you need to have methods that aren't specific to any particular instance, but still, involve the class in some way. The most interesting thing about them is that they can be overridden by subclasses.

So If you want to access a property of a class as a whole, and not the property of a specific instance of that class, use a class method.

class MyClass():

    TOTAL_OBJECTS=0

    def __init__(self):
        MyClass.TOTAL_OBJECTS = MyClass.TOTAL_OBJECTS+1

    @classmethod
    def total_objects(cls):
        print("Total objects: ",cls.TOTAL_OBJECTS)

# Creating objects
my_obj1 = MyClass()
my_obj2 = MyClass()
my_obj3 = MyClass()

# Calling class method
MyClass.total_objects()

Output:

Total objects:  3

Now if we inherit this class into a child class and declare the TOTAL_OBJECTS variable there and call the class method from child class it will return the total object count for the child class.

class MyClass():

    TOTAL_OBJECTS=0

    def __init__(self):
        MyClass.TOTAL_OBJECTS = MyClass.TOTAL_OBJECTS+1

    @classmethod
    def total_objects(cls):
        print("Total objects: ",cls.TOTAL_OBJECTS)

# Creating objects of parent class
my_obj1 = MyClass()
my_obj2 = MyClass()


# Creating a child class
class ChildClass(MyClass):
    TOTAL_OBJECTS=0
    pass

ChildClass.total_objects()

Output:

Total objects:  0
Wrapping it up

@classmethod is used in a superclass to define how that method should behave when it's called by different child classes. Whereas a @staticmethod is used when we want to return the same thing regardless of the child class that we are calling.

Also, keep a note that calling a @classmethod involves an additional memory allocation that calling a @staticmethod or regular function does not.


PYTHON

Latest Articles

Latest from djangocentral

Capturing Query Parameters of request.get in Django

In Django, the request object contains a variety of information about the current HTTP request, including the query parameters. Query parameters are a way to pass additional information in the URL and are used to filter or sort data. The request object p…
Read more →

2 min read

Understanding related_name in Django Models

In Django, related_name is an attribute that can be used to specify the name of the reverse relation from the related model back to the model that defines the relation. It is used to specify the name of the attribute that will be used to access the relat…
Read more →

2 min read