Why is it permitted to call a class method from an instance? How is it useful to do this?
-
1It's not so much "is there a use case" as "is the behavior defined", and it is: a class method always receives a class as its first argument. When invoked from a class, that class is passed. When invoked from an instance, the type of that instance is passed. – chepner Sep 23 '22 at 21:19
-
If I invoke the class method with the instance, what would be passed in the cls argument of the method, the class or the instance? – Shiva Gupta Sep 23 '22 at 21:24
-
2The class will be passed. The instance is only used to look up the method. The `@classmethod` decorator ensures that the underlying function has the class passed to it; and it knows which class to use because of the lookup process. – Karl Knechtel Sep 23 '22 at 21:25
-
See also: [How do I disallow a classmethod from being called on an instance?](/questions/42322936). – Karl Knechtel Sep 23 '22 at 21:33
3 Answers
Suppose we use @classmethod
to create an abstract factory:
class Base:
def __init__(self, a, b, c):
self.a, self.b, self.c = a, b, c
@classmethod
def from_string(cls, data):
print(f'Making a {cls.__name__} instance from {data!r}.')
a, b, *c = data.split()
return cls(a, b, c)
class Derived(Base):
pass
Testing it:
>>> d = Derived.from_string('the quick brown fox jumps over the lazy dog')
Making a Derived instance from 'the quick brown fox jumps over the lazy dog'.
>>> d.c
['brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']
By using an instance, we can create an instance that is known to be of the same type as the one we invoked:
>>> d2 = d.from_string('pack my box with five dozen liquor jugs')
Making a Derived instance from 'pack my box with five dozen liquor jugs'.
>>> assert(type(d2) is type(d)) # passes
Whether looked up directly in the class, or from an instance, @classmethod
ensures that the class is passed as cls
.

- 62,466
- 11
- 102
- 153
It's useful when you have instances of different classes, and the classes have different implementations of the same class method. Calling instance.method()
will call the implementation appropriate for that instance's class. You can think of it as a shortcut for
type(instance).method()
Example:
class Class1:
@classmethod
def method(cls):
return "Class 1"
class Class2:
@classmethod
def method(cls):
return "Class 2"
instance = Class1() if random.randint(1, 2) == 1 else Class2()
print(instance.method()) # Prints Class 1 or Class 2

- 741,623
- 53
- 500
- 612
Suppose you've got a class that has six different methods on it. Five of them use self
and do something complicated. But the sixth one just returns a constant, because it never changes based on the instance. It would be annoying if I had to remember to call
my_object.get_value()
my_object.frobnicate()
my_object.ping(100)
my_object.foobar(variable)
my_object.add(10)
type(my_object).version_id()
So, for consistency, it makes sense to be able to call that last one (which depends only on the class) on instances as well.

- 62,821
- 6
- 74
- 116