The idea of method or function definition is probably language and domain agnostic, i.e., more of a rational way of writing reusable codes and a clever way of implementing DRY (Don’t Repeat Yourself)
A method definition in Python is as easy as in any other language. Functional block starts with a def keyword, followed by a function name and parentheses.
So, how does a method work in Python? We will first look into the instance methods. Let’s start with a familiar example.
Here, we have a class called Animal with two methods __init__ and animal_name, where former is a special method and later is a plain pythonic instance method declaration. It can be seen that we have passed ‘self’ keyword in both these methods. What does this mean? Let us try to understand it with an example.
Traceback (most recent call last):
TypeError: unbound method animal_name() must be called with Animal instance as first argument (got nothing instead)
The keyword ‘self’ is just a naming convention (other words can also be used). By providing ‘self’ as the first argument we are specifying that the methods within the class Animal are bound to the class instance, i.e, the first argument passed is itself the instance of a class. The below example will make it clearer.
>>>animal = Animal(‘dog’)
‘This is a dog’
In this case, we create an instance of class Animal which is passed as the first argument to the method ‘animal_name’ or more precisely speaking Bound method which is same as doing:
‘This is a cat’
Bound and Unbound methods
In simple terms, a bound method is the one which is dependent on the instance of the class as the first argument. That’s why they are called instance methods and in our example, animal_name is an instance method. Staticmethods are examples of unbound methods. Speaking in terms of our previous example we can find an analogy, any animal_name is first bound to Animal first and then supposed to display its characteristics.
In simpler terms, staticmethods are those methods which are not bound to the class instance and deal only with the arguments it takes. To declare a staticmethod we just have to add ‘@staticmethod’ decorator over the method definition as shown in the next example.
We can see in the example that we have not added ‘self’ keyword in the message which suggests that it is not related to the class or its instance. Since it is not related to class anyway, it is not mandatory to call staticmethods with instance of class. Following example will give a clear idea.
>>>a = Animal(‘dog’)
Hence, we see that staticmethods are not bound to the class. Also, the analogy with the example is that the message (“Love animals”) is more of a generic type and not related to the class, so staticmethods are the ones which do not relate to class anyway. By using staticmethods, we are essentially trying to demonstrate that the method depends on arguments and does not touch the instance (i.e. ‘self’). We can see the implementation in datetime module of CPython repository.
Much like staticmethods, classmethods also are independent of the instance of class but are dependent on the class itself, i.e., bound to the class. Thus, quite obviously it takes class as the first parameter. Classmethods can be created with ‘@classmethod’ decorator as described in the next example.
In the above example, we are passing ‘cls’ as the class reference. Let’s see how this works.
The example makes it clear that classmethods are bound to the class itself and thus, is powerful enough to change the class properties; in this case, the class is variable. Also, it is notable that much like staticmethods, these do not need to be called on class objects. Hence, classmethods are also called factory methods or alternate constructors. An example of alternate constructor is shown below:
>>>animal = Animal(2)
>>>animal = Animal.change_legs()
An implemented example of classmethod can be seen here. Apart from classmethods and staticmethods, abstract methods are of great usage. You can read about abstractmethods and abstract base classes here. Happy Python!