Instance, Class and Static methods in Python
Tags: programming, python, programmers
Published: 2024-04-07 12:51:37

<p>Methods are functions that&nbsp;are associated with a particular object or class.&nbsp;The three types of methods are :</p>

<div>
<ol>
	<li><strong>Instance methods</strong>: These methods are associated with instances of a class&nbsp;and can access and modify the data within an&nbsp;instance.</li>
	<li><strong>Class methods</strong>: These methods are associated with a class rather than instances.&nbsp; They are used to create or modify class-level properties or behaviors.</li>
	<li><strong>Static methods</strong>: These are utility methods that&nbsp;do not have access to any object-level or class-level data.</li>
</ol>
</div>

<p>Understanding the difference between the 3 types of&nbsp; methods will be crucial in ensuring that you write classes that&nbsp; are properly organized, efficient, easy to maintain and which are a close&nbsp;reflection&nbsp;of the real life objects they are being modeled after.&nbsp;</p>

<p>The following&nbsp; example shows how each of these methods are defined in a class. We will talk about the technical details in a while.</p>

<div class="example">
<pre>
<code class="language-python">class Example:
    #define an instance method
    def method(self):
        Return "I am an instance method"
    
    #define a class method
    @classmethod
    def class_method(cls):
        return "I am a class method"
    
    #Define a static method
    @staticmethod
    def static_method():
        return "I am a static method"</code></pre>
</div>

<h2>Instance Methods</h2>

<p>Instance methods are functions defined inside a class that perform operations on instances rather than the class itself.</p>

<p>If you have interacted with Python classes, it is likely that you have encountered and used&nbsp;instance methods.&nbsp;You can easily identify the methods&nbsp;by looking for the&nbsp; parameter&nbsp;<code>self</code> in the method definition.</p>

<div class="autorun example">
<pre>
<code class="language-python">#define the class
class Example:
    #Define an instance method
    def method(self):
        return "I am an instance method. I will only work when called by objects of this class!"

#create an object
e = Example()
#call an instance method
print(e.method())</code></pre>
</div>

<p>Instance methods&nbsp;are able to access and modify an instance variables and data.&nbsp;</p>

<div class="autorun example">
<pre>
<code class="language-python">class Student:

   #Define the constructor
   def __init__(self, name, grade):
       self.name = name  
       self.grade = grade

   #define other instance methods
   def change_grade(self, new_grade):
       self.grade = new_grade 

   def print_info(self):
       print(f"{self.name} is in grade {self.grade}") 

s1 = Student("Bob", 9)

s1.print_info() 

s1.change_grade(10)

s1.print_info()</code></pre>
</div>

<div style="background:#ffeeee; padding:5px 10px">
<p>&nbsp;Note: Calling an instance method from the class itself will raise a&nbsp;<code>TypeError</code>.</p>
</div>

<div class="autorun example">
<pre>
<code class="language-python">#define the class
class Example:

    #Define an instance method
    def method(self):
        return "I am an instance method. I will only work when called by objects!"

#Try calling an instance method from the class itself. An error is raised!.
print(Example.method())</code></pre>
</div>

<h4>Instance methods cannot modify class level variables</h4>

<p>Instance methods are only able to access and modify instance variables, which exist only within the scope of an instance of a class. As such, they cannot access or modify class level variables.</p>

<div class="autorun example">
<pre>
<code class="language-python">class Example:
   #Define a class level variable
   x = 10

   #The following method will modify the value of x at instance level rather than at class level
   def modify(self):
      self.x = 1000


print(Example.x)

e = Example()
e.modify()
print(Example.x)</code></pre>
</div>

<h2>Class Methods</h2>

<p>Class methods are methods that are bound to a class rather than to objects.&nbsp;These methods can be called directly from the class itself as well as from the instances.&nbsp;</p>

<p>Class methods&nbsp;take&nbsp;<code>cls&nbsp;</code>as the first argument. The&nbsp;<code>cls&nbsp;</code>argument&nbsp;is a reference to the class, and is used to access class attributes and methods. It is analogous to the <code>self</code> argument for instance methods.</p>

<p>We use the&nbsp;<a href="https://www.pynerds.com/python-classmethod-function/">@classmethod</a>&nbsp;decorator to define a class method. The syntax is as follows:</p>

<div class="nocopy syntax">
<pre>
<code class="language-python">@classmethod
def method_name(cls):
    #method body</code></pre>
</div>

<p>Class methods&nbsp; operate on the class itself, rather than on an instances of the class. They are used to provide general functionality for objects of that particular class.</p>

<p>Consider the following example:</p>

<div class="autorun example">
<pre>
<code class="language-python">class Example:
   #Define a class level variable
   x = 10

   #The following method will modify the value at class level
   @classmethod
   def modify(cls, v):
      """Modify the value of the class level variable x with the new variable v"""
      cls.x = v


print(Example.x)

#Call class method from the class itself
Example.modify(100)
print(Example.x)

#call class method from an instance
e = Example()
e.modify(1000)
print(Example.x)</code></pre>
</div>

<p>The following example shows how we can keep a count of all the active instances of a class using class method.</p>

<div class="autorun example">
<pre>
<code class="language-python">#Define the class
class Example:
   
   #The variable to keep the count
   count = 0

   def __init__(self):
      self.increase_count() #Call increas count each time a new object is created.
   
   @classmethod
   def increase_count(cls):
       """This method increases the global level variable, 'count' """
       cls.count +=1
  
   @classmethod
   def get_count(cls):
       return cls.count

#The following exampls demonstrate the methods at work.

print(Example.get_count())

e1 = Example()
print(Example.get_count())

e2 = Example()
e3 = Example()
print(Example.get_count())

e4 = Example()
e5 = Example()
print(e5.get_count())
   </code></pre>
</div>

<h2>Static methods</h2>

<p>From the above discussions, instance methods operate on instances, while class method operate on the class itself.</p>

<p>Static methods, &nbsp;as the name suggests are just static.&nbsp;They belong to a class but the do not have access to class or instance variables. They are simply meant for&nbsp;providing utility services that are not class or instance specific.</p>

<div style="background:#ffeeee; padding:5px 10px">
<p>Note: While instance method&nbsp; and class methods always take&nbsp;<code>self</code>,&nbsp;&nbsp;<code>cls&nbsp;</code>as their first arguments respectively.&nbsp;Static methods do not take any mandatory argument as the&nbsp;first argument. This is because they are not bound to either the class or instances and are simply called directly.</p>
</div>

<p>Static methods are defined using the&nbsp;<a href="https://www.pynerds.com/python-staticmethod-function/">@staticmethod</a>&nbsp;decorator.&nbsp; The syntax is as follows:</p>

<div class="nocopy syntax">
<pre>
<code class="language-python">@staticmethod
def method_name(params):
   #method body</code></pre>
</div>

<div class="autorun example">
<pre>
<code class="language-python">class Example:

   @staticmethod
   def method():
      print("I am a static method.")

Example.method()

e = Example()
e.method()</code></pre>
</div>

<p>As shown above, static methods can be called from the class itself as well as from the instances.</p>

<p>Consider if we have the class <strong>Rectangle</strong>, we can define a utility/static methods for calculating the area and the perimeter.</p>

<div class="autorun example">
<pre>
<code class="language-python">#define the class

class Rectangle:
   
   def __init__(self, w, l):
       self.width = w
       self.length = l

   #define some instance methods
   def area(self):
       """This method will call the static method 'calculate_area' """
       return self.calculate_area(self.width, self.length)

   def perimeter(self):
      """This method will call the static method 'calculate_perimeter' """
      return self.calculate_perimeter(self.width, self.length)

   #Define utilty methods that are accessible from the class as well as instances
   @staticmethod
   def calculate_area(w, l):
       return w * l

   @staticmethod
   def calculate_perimeter(w, l):
       return 2 * ( w + l)

#Use utility methods from the class
print(Rectangle.calculate_area(7, 4))
print(Rectangle.calculate_perimeter(7, 4))

#from instances
r = Rectangle(20, 30)
print(r.area())
print(r.perimeter())

r2 = Rectangle(100, 50)
print(r2.area())
print(r2.perimeter())
</code></pre>
</div>

<h2>Summary</h2>

<div>
<ol>
	<li>Instance methods operate at instance level. They take&nbsp;<code>self&nbsp;</code>as their first argument</li>
	<li>Class methods operate at class level, they have access to class variables. They are defined using the @classmethod decorator.&nbsp; They take&nbsp;<code>cls&nbsp;</code>as the first argument.</li>
	<li>Static methods are utility methods, they do not have access to class or instance variables. They are defined using the @staticmethod decorator and they do not take any mandatory first argument.&nbsp;</li>
</ol>
</div>

<div class="related"><h3>Related articles</h3><hr><ul><li><p><a class="text-success" href="https://www.pynerds.com/pythons-applications-in-modern-software-development/">Python's Applications in Modern Software Development</a><li><p><a class="text-success" href="https://www.pynerds.com/python-classmethod-function/">Python classmethod() Function</a><li><p><a class="text-success" href="https://www.pynerds.com/python-staticmethod-function/">Python staticmethod() Function</a><li><p><a class="text-success" href="https://www.pynerds.com/python-static-or-class-variables/">Python static or class variables</a><li><p><a class="text-success" href="/introduction-to-object-oriented-programming/">Introduction to Object Oriented Programming</a><li><p><a class="text-success" href="https://www.pynerds.com/python-classes-init-method/">Python classes __init__() method</a><li><p><a class="text-success" href="https://www.pynerds.com/python-classes-str-method/">Python Classes __str__() Method</a><li><p><a class="text-success" href="https://www.pynerds.com/difference-between-function-and-method-in-python/">Difference between function and method in Python</a><li><p><a class="text-success" href="https://www.pynerds.com/introduction-to-concurrent-programming-in-python/">Introduction to concurrent programming in Python</a></ul></div>