Understand the usage of python classmethods
While trying to understand the difference between staticmethod and classmethod I landed on this blog post. I was bit confused after reading the comment “classmethod can be helpful in case of inheritence instead of having one staticmethod calling another staticmethod”.
I used the same example in blog post to extend it bit to understand the practical implementation.
I am overriding the compute_area staticmethod function in inherited class this function was called by another staticmethod compute_volume. NOTE: I need to call compute_area
from compute_volume
using Pizza.compute_area(radius)
where Pizza
is the class name, you can’t use self
instead of Pizza
.
import math
class Pizza():
def __init__(self, radius, height):
self.radius = radius
self.height = height
@staticmethod
def compute_area(radius):
return math.pi * (radius ** 2)
@staticmethod
def compute_volume(height, radius):
return height * Pizza.compute_area(radius)
def get_volume(self):
return self.compute_volume(self.height, self.radius)
class Italian(Pizza):
@staticmethod
def compute_area(radius):
print("In inherited")
return math.pi * (radius ** 2)
instance1=Pizza(4,5)
print(instance1.get_volume())
instance2=Italian(5,6)
print(instance2.get_volume())
Result of run are:
251.327412287
471.238898038
It ran fine but it didn’t run the overrided compute_area
method which I defined in Italian
class instead used compute_area
from parent class. It happened because we are calling compute_area
using Pizza
classname in compute_volume
method.
Let’s use classmethod
now instead of staticmethod
to define compute_volume method in parent class.
import math
class Pizza():
def __init__(self, radius, height):
self.radius = radius
self.height = height
@staticmethod
def compute_area(radius):
return math.pi * (radius ** 2)
#@staticmethod
#def compute_volume(height, radius):
# return height * Pizza.compute_area(radius)
@classmethod
def compute_volume(cls, height, radius):
return height * cls.compute_area(radius)
def get_volume(self):
return self.compute_volume(self.height, self.radius)
class Italian(Pizza):
@staticmethod
def compute_area(radius):
print("In inherited")
return math.pi * (radius ** 2)
instance1=Pizza(4,5)
print(instance1.get_volume())
instance2=Italian(5,6)
print(instance2.get_volume())
Results of run are:
251.327412287
In inherited
471.238898038
This gives us expected results because classname was dynamically was replaced with Italian
in-place of cls
while calling staticmethod
from classmethod
.