In Python, a classmethod is a method that is bound to the class and not the instance of the class. A classmethod is defined using the @classmethod
decorator, and it takes the class itself as the first argument (cls). A classmethod can be called on the class itself, or on any instance of the class.
On the other hand, a staticmethod is a method that is neither bound to the class nor the instance of the class. A staticmethod is defined using the @staticmethod
decorator, and it does not take any special arguments. A staticmethod can be called on the class itself, or on any instance of the class.
In this article, we will explore the use cases for classmethods and staticmethods, and how to define and use them in Python.
Defining Classmethods:
To define a classmethod, we use the @classmethod
decorator followed by the cls
argument, like this:
class MyClass:
def __init__(self, arg):
self.arg = arg
@classmethod
def my_classmethod(cls, arg):
return cls(arg)
In the example above, we have defined a class MyClass
with an instance variable arg
and a classmethod my_classmethod
. The classmethod takes a single argument arg
, and it returns an instance of MyClass
with the value of arg
as the arg
instance variable.
We can call the classmethod on the class itself, or on any instance of the class, like this:
# call the classmethod on the class itself
obj1 = MyClass.my_classmethod('hello')
print(obj1.arg) # Output: 'hello'
# call the classmethod on an instance of the class
obj2 = MyClass('world')
obj3 = obj2.my_classmethod('hello')
print(obj3.arg) # Output: 'hello'
Use Cases for Classmethods:
Classmethods are useful in cases where we want to create an instance of a class based on a specific input or configuration. For example, we can use a classmethod to create an instance of a class with a certain attribute value, or with a value that is calculated based on the input.
Here’s an example of using a classmethod to create an instance of a class with a certain attribute value:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_string(cls, string):
name, age = string.split(',')
return cls(name, age)
# create a Person object using the from_string classmethod
p = Person.from_string('John, 30')
print(p.name) # Output: 'John'
print(p.age) # Output: '30'
In the example above, we have defined a class Person
with an instance variable name
and an instance variable age
. We have also defined a classmethod from_string
, which takes a string as an input and creates an instance of Person
with the name
and age
values extracted from the string.
We can use the from_string
classmethod to create an instance of Person
from a string, rather than calling the constructor Person(name, age)
directly. This can be useful in cases where we want to create an instance of a class based on a string input, such as reading data from a file.
Defining Staticmethods:
To define a staticmethod, we use the @staticmethod
decorator, like this:
class MyClass:
def __init__(self, arg):
self.arg = arg
@staticmethod
def my_staticmethod(arg):
return arg
In the example above, we have defined a class MyClass
with an instance variable arg
and a staticmethod my_staticmethod
. The staticmethod takes a single argument arg
, and it returns the value of arg
.
We can call the staticmethod on the class itself, or on any instance of the class, like this:
# call the staticmethod on the class itself
result1 = MyClass.my_staticmethod('hello')
print(result1) # Output: 'hello'
# call the staticmethod on an instance of the class
obj = MyClass('world')
result2 = obj.my_staticmethod('hello')
print(result2) # Output: 'hello'
Use Cases for Staticmethods:
Staticmethods are useful in cases where we want to define a method that does not depend on the instance or the class itself, but it is related to the class in some way. A staticmethod is just a function that is defined within a class, but it does not have any special behavior.
Here’s an example of using a staticmethod to define a utility function that is related to the class:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@staticmethod
def is_adult(age):
return age >= 18
# call the is_adult staticmethod
result = Person.is_adult(20)
print(result) # Output: True
In the example above, we have defined a class Person
with an instance variable name
and an instance variable age
. We have also defined a staticmethod is_adult
, which takes an age
as an input and returns a boolean value indicating whether the person is an adult or not.
The is_adult
staticmethod does not depend on the instance or the class itself, it is just a utility function that is related to the class Person
. We can call the staticmethod on the class itself, or on any instance of the class, to check if a person with a certain age is an adult.
Conclusion:
In this article, we have learned about classmethods and staticmethods in Python, and how to define and use them. Classmethods are useful in cases where we want to create an instance of a class based on a specific input or configuration. Staticmethods are useful in cases where we want to define a method that does not depend on the instance or the class itself, but it is related to the class in some way. We hope this article has been helpful and that you have a better understanding of classmethods and staticmethods in Python.
Exercises
To review these concepts, we will go through a series of exercises designed to test your understanding and apply what you have learned.
Write a class Rectangle
that has a width
property and a height
property, and define a classmethod from_square
that creates an instance of Rectangle
with the given width and height set to the same value. Test your class by creating a Rectangle
object using the from_square
classmethod, and print the width and the height of the object.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
@classmethod
def from_square(cls, side):
return cls(side, side)
# create a Rectangle object using the from_square classmethod
r = Rectangle.from_square(5)
print(r.width) # Output: 5
print(r.height) # Output: 5
Write a class Point
that has an x
property and a y
property, and define a staticmethod distance
that calculates the distance between two points. Test your class by creating two Point
objects, and use the distance
staticmethod to calculate the distance between them.
import math
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
@staticmethod
def distance(p1, p2):
dx = p1.x - p2.x
dy = p1.y - p2.y
return math.sqrt(dx**2 + dy**2)
# create two Point objects
p1 = Point(1, 2)
p2 = Point(4, 5)
# calculate the distance between p1 and p2
result = Point.distance(p1, p2)
print(result) # Output: 3.605551275463989
Write a class Polygon
that has a sides
property and a perimeter
property, and define a classmethod from_side_lengths
that creates an instance of Polygon
with the given side lengths. Test your class by creating a Polygon
object using the from_side_lengths
classmethod, and print the sides and the perimeter of the object.
class Polygon:
def __init__(self, sides, perimeter):
self.sides = sides
self.perimeter = perimeter
@classmethod
def from_side_lengths(cls, *side_lengths):
return cls(side_lengths, sum(side_lengths))
# create a Polygon object using the from_side_lengths classmethod
p = Polygon.from_side_lengths(5, 7, 9)
print(p.sides) # Output: (5, 7, 9)
print(p.perimeter) # Output: 21
Write a class Shape
that has a color
property, and define a staticmethod parse_color
that parses a color string into a tuple of RGB values. Test your class by creating a Shape
object with a color string and use the parse_color
staticmethod to parse it into RGB values.
class Shape:
def __init__(self, color):
self.color = color
@staticmethod
def parse_color(color_string):
# split the color string into separate R, G, B values
r, g, b = color_string.split(",")
# return the values as a tuple
return (int(r), int(g), int(b))
# create a Shape object with a color string
s = Shape("255,128,0")
# parse the color string into RGB values
rgb = Shape.parse_color(s.color)
print(rgb) # Output: (255, 128, 0)
Write a class Card
that has a suit
property and a value
property, and define a classmethod from_string
that creates an instance of Card
with the given suit and value extracted from a string. Test your class by creating a Card
object using the from_string
classmethod, and print the suit and value of the object.
class Card:
def __init__(self, suit, value):
self.suit = suit
self.value = value
@classmethod
def from_string(cls, card_string):
# split the card string into suit and value
suit, value = card_string.split("-")
return cls(suit, value)
# create a Card object using the from_string classmethod
c = Card.from_string("hearts-7")
print(c.suit) # Output: hearts
print(c.value) # Output: 7