Static vs Class vs Instance variables/methods in Python

Not like Java or C#, the simplicity of Python sometimes makes us very confused about these terms.
When a method should be defined as Class method or Static method or an Instance method ? the relationship between Class variable and Instance variable ?

First, Let’s differentiate Class attributes vs Instance attributes with below example:

class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

A Python class attribute is an attribute of the class , rather than an attribute of an instance of a class. It means this attribute will be shared among instances.

foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var, bar.class_var, bar.i_var
## 1, 2, 1, 3
MyClass.class_var
## 1

what happen if class variable is modified ?

  • If a class attribute is set by accessing the class, it will override the value for all instances
foo = MyClass(2)
foo.class_var
## 1
MyClass.class_var = 2
foo.class_var
## 2
  • If a class variable is set by accessing an instance, it will override the value only for that instance.
foo = MyClass(2)
foo.class_var
## 1
foo.class_var = 2
foo.class_var
## 2
MyClass.class_var
## 1
  • But be careful with mutable attribute like List, Dict. If instance tries to append to a list, that list would be altered over time on an instance-by-instance. To avoid this , we can use assignment instead of appending.

And one thing we should keep in mind that if you want to have a unique data for each instance, it should be define inside instance constructor __init__(self, arg), don’t use class attribute. Only use this in case tracking all data across all instances of a given class.

class MyClass(object):
    class_data = []
    def __init__(self, i_var):
        self.i_var = i_var

foo = MyClass(2)
bar = MyClass(3)
foo.class_data.append('a')
bar.class_data.append('b') 
foo.class_data , bar.class_data
## ['a', 'b'], ['a', 'b']

foo.class_data = ['a']
bar.class_data = ['b'] 
foo.class_data , bar.class_data
## ['a'], ['b']

When Should you Use Python Class Attributes

  • Storing constants which sharing for all instances.
  • Defining default values and modify it by instance if the instance need a different value.
  • Tracking all data across all instances of a given class

Now, move to part 2, Class method vs Static method vs Instance method:

Start from Instance method. It is simply a method dedicated to instance. Only an instance can access this method. you can not access it by calling the class. It also needs to take the first argument as “self”.

class MyClass():
    def init(self):
        self.data = []

    def f(self, arg):
        print(arg)

foo = MyClass()
foo.f('hello')
# hello

Class Method:

A class method is a method which is bound to the class and not the object of the class. They have the access to the state of the class as it takes a class parameter that points to the class and not the object instance. The @classmethod decorator needs to add in class method.

Static Method:

A static method is also a method which is bound to the class and not the object of the class. But not like class method , A static method can’t access or modify class state.

from datetime import date 
  
class Person: 
    def __init__(self, name, age): 
        self.name = name 
        self.age = age 
      
    # a class method to create a Person object by birth year. 
    @classmethod
    def fromBirthYear(cls, name, year): 
        return cls(name, date.today().year - year) 
      
    # a static method to check if a Person is adult or not. 
    @staticmethod
    def isAdult(age): 
        return age > 18
  
person1 = Person('mayank', 21) 
person2 = Person.fromBirthYear('mayank', 1996) 
  
print person1.age 
print person2.age 
  
# print the result 
print Person.isAdult(22) 

One more example for Class Method.  Imagine if a Student object could be serialized in to many different formats. You could use class method to parse them and create a Student Object.

class Student(object):

    @classmethod
    def from_string(cls, name_str):
        first_name, last_name = map(str, name_str.split(' '))
        student = cls(first_name, last_name)
        return student

    @classmethod
    def from_json(cls, json_obj):
        # parse json...
        return student

    @classmethod
    def from_pickle(cls, pickle_file):
        # load pickle file...
        return student

Let’s compare Class method vs Static method:

  • A class method takes cls as first parameter while a static method needs no specific parameters.
  • A class method can access or modify class state while a static method can’t access or modify it.
  • In general, static methods know nothing about class state. They are utility type methods that take some parameters and work upon those parameters. On the other hand class methods must have class as parameter.
  • We use @classmethod decorator in python to create a class method and we use @staticmethod decorator to create a static method in python.

When to use ?

  • We generally use class method to create factory methods. Factory methods return class object ( similar to a constructor ) for different use cases.
  • We generally use static methods to create utility functions.

Reference Sources:

https://www.toptal.com/python/python-class-attributes-an-overly-thorough-guide

https://www.geeksforgeeks.org/class-method-vs-static-method-python/?ref=rp

https://stackabuse.com/pythons-classmethod-and-staticmethod-explained/

Leave a comment