Python’s Instance, Class and Static Methods

This article uncovers the class methods, static methods and regular instance methods.

--

Overview

As per the Python’s data model, Python offers three types of methods namely instance, class and static methods. Let’s peek in to what happens behind the scenes for each method type. Developing their understanding will help us write our code more efficiently and more Pythonic. Being not aware of the concepts behind them might get us confused which may lead to some surprising results. Let’s begin with a toy example having all the three methods.

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

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

Instance Methods

They are most widely used methods. Instance method receives the instance of the class as the first argument, which by convention is called self, and points to the instance of our class ToyClass. However it can take any number of arguments.
Using the self parameter, we can access the other attributes and methods on the same object and can change the object state. Also, using the self.__class__ attribute, we can access the class attributes, and can change the class state as well. Therefore, instance methods gives us control of changing the object as well as the class state.

A built-in example of an instance method is str.upper():

>>> "welcome".upper()   # <- called on the str object
'WELCOME'

Class Methods

A class method accepts the class as an argument to it which by convention is called cls. It take the cls parameter, which points to the class ToyClass instead of the object of it. It is declared with the @classmethod decorator.

Class methods are bound to the class and not to the object of the class. They can alter the class state that would apply across all instances of class but not the object state.

A builtin example is dict.fromkeys() which returns a new dictionary with a given sequence of elements as the keys of the dictionary.

dict.fromkeys('AEIOU')  # <- called using dict class
{'A': None, 'E': None, 'I': None, 'O': None, 'U': None}

Static Methods

A static method is marked with a @staticmethod decorator to flag it as static. It does not receive an implicit first argument (neither self nor cls).
It can also be put as a method that “does’t know its class”.
Hence a static method is merely attached for convenience to the class object. Hence static methods can neither modify the object state nor class state. They are primarily a way to namespace our methods.

Okay enough with the theory, let’s understand the behaviour of each method by creating instances of our above class and calling the instancemethod, classmethod and staticmethod respectively.

>>> obj = ToyClass()
>>> obj.instancemethod()
('instance method called', ToyClass instance at 0x10f47e7a0>)
>>> ToyClass.instancemethod(obj)
('instance method called', ToyClass instance at 0x10f47e7a0>)

Above calls corroborated the fact that instancemethod has access to the object <ToyClass instance> via the self argument. Also as seen above, obj.instancemethod() is syntactic sugar. We can also pass the object manually using ToyClass.instancemethod(obj) . Let’s invoke the class method now.

>>> obj.classmethod()
('class method called', <class ToyClass at 0x10f453a10>)

It shows that classmethod() has access to the ToyClass instance but not the ToyClass object instance. Remember, in Python, everything is an object. That means the class is also an object, and can be passed as an argument to a function.
NOTE: We can name arguments self and cls anything we want.

def instancemethod(self, ...)
def classmethod(cls, ...)
-------equivalent to----------def instancemethod(my_object, ...)
def classmethod(my_class, ...)

They are just a naming convention being followed. However they should be the first in the list of parameters. Let’s invoke the static method

>>> obj.staticmethod()
static method called

Yes, a little surprising at first, but we can invoke static method using object of our class. Since the dot-call syntax is a syntactic sugar. What happens behind the scenes is in case of staticmethod, no argument ( self or cls ) is passed to the method.
Therefore, staticmethod don’t have access to class state or the class instance state. They only work with data passed in as arguments. Now let’s try invoking the above methods using class itself.

>>> ToyClass.classmethod()
('class method called', <class ToyClass at 0x10f453a10>)
>>> ToyClass.staticmethod()
'static method called'
>>> ToyClass.instancemethod()
TypeError: unbound method instancemethod()
must be called with ToyClass instance as
first argument (got nothing instead)

So we get expected results, calling classmethod and staticmethod using class works fine, however calling an instancemethod throws a TypeError. Since no object instance is created hence self argument cannot be populated.

Now having got the basic distinction between the three methods, let’s see one more practical example to get a deeper understanding of where to use which type of method. The below sample has been taken from here, since it demonstrates of usage of different methods clearly.

from datetime import dateclass Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_birth_year(cls, name, year):
return cls(name, date.today().year - year)
@staticmethod
def is_adult(age):
return age > 18
person1 = Person('Sarah', 25)
person2 = Person.from_birth_year('Roark', 1994)
>>> person1.name, person1.age
Sarah 25
>>> person2.name, person2.age
Roark 24
>>> Person.is_adult(25)
True

When to use each method type?

It may seem tough and daunting decision choosing between the types of methods in Python, but will get the hang of it with a bit of practice.

We generally use the class methods to create factory methods which returns the class object for a different use case. As above, classmethod from_birth_year is used to create a class object from a birth year instead of age.
Static methods however are primarily used to create utility function and work on data provided to them in arguments.

Things to remember

  • Instance methods can access the instance through self as well as the class via self.__class__ attribute.
  • Class methods can’t access the instance (self) but they have access to the class itself via cls.
  • Static Methods work like regular functions but belong to the class’s namespace. Static methods don’t have access to cls or self.
  • Even if we write tiny scripts for fun, learning another OOP feature of Python is a great skill to know, and can help to make your code easier to troubleshoot, and easier to reuse in the future.

--

--

Rachit Tayal
Python Features

Sports Enthusiast | Senior Deep Learning Engineer. Python Blogger @ medium. Background in Machine Learning & Python. Linux and Vim Fan