We know that both classmethod and staticmethod can be used as decorators of functions and can be used for methods that do not involve class member variables. However, if you check the Python standard library, you will know that classmethod (1052) is used much more than staticmethod(539). Why?

This starts with the difference between static method and classmethod.
1. In terms of calling form, the two are similar in usage
First, let's talk about what is a class and what is an instance. For example, a = A(), then a is a class and a is an instance.
In terms of definition form, the first parameter of clasmethod is cls, which represents the class itself. The first parameter of ordinary method is self, which represents the instance itself. The parameters of staticmethod are no different from ordinary functions.
In terms of call form, both staticmethod and classmethod support class direct call and instance call.
class MyClass: def method(self): """ Instance methods need a class instance and can access the instance through `self`. """ return 'instance method called', self @classmethod def classmethod(cls): """ Class methods don't need a class instance. They can't access the instance (self) but they have access to the class itself via `cls`. """ return 'class method called', cls @staticmethod def staticmethod(): """ Static methods don't have access to `cls` or `self`. They work like regular functions but belong to the class's namespace. """ return 'static method called' # All methods types can be # called on a class instance: >>> obj = MyClass() >>> obj.method() ('instance method called', <MyClass instance at 0x1019381b8>) >>> obj.classmethod() ('class method called', <class MyClass at 0x101a2f4c8>) >>> obj.staticmethod() 'static method called' # Calling instance methods fails # if we only have the class object: >>> MyClass.classmethod() ('class method called', <class MyClass at 0x101a2f4c8>) >>> MyClass.staticmethod() 'static method called'
2. Let's talk about static method first.
If staticmethod is added to a class function, it usually means that the calculation of this function does not involve class variables and can be used without class instantiation, that is, the relationship between this function and this class is not very close. In other words, functions decorated with staticmethod can also be defined outside the class. I sometimes wonder whether to use staticmethod in a class or utils Write a separate function in py? For example, the following Calendar class:
class Calendar: def __init__(self): self.events = [] def add_event(self, event): self.events.append(event) @staticmethod def is_weekend(dt:datetime): return dt.weekday() > 4 if __name__ == '__main__': print(Calendar.is_weekend(datetime(2021,12,27))) #output: False
The function is_ Weeken is used to determine whether a day is a weekend. It can be defined outside Calendar as a public method, so that the class name Calendar does not need to be added when using this function.
However, some cases are best defined in the class, that is, this function leaves the context of the class and does not know how to call it. For example, the following class is used to judge whether the matrix can be multiplied. The more readable call form is matrix can_ multiply:
from dataclasses import dataclass @dataclass class Matrix: shape: tuple[int, int] # python3. The writing of this type declaration is supported after 9 @staticmethod def can_multiply(a, b): n, m = a.shape k, l = b.shape return m == k
3. Say classmethod again.
First, we understand it from the form of clasmethod. Its first parameter is cls, which represents the class itself. That is, we can call the class constructor cls() in the classmethod function to generate a new instance. From this point, we can infer its usage scenario:
- When we need to call the constructor again, that is, when we create a new instance object
- You need to return a new instance without modifying the existing instance
For example, the following code:
class Stream: def extend(self, other): # modify self using other ... @classmethod def from_file(cls, file): ... @classmethod def concatenate(cls, *streams): s = cls() for stream in streams: s.extend(stream) return s steam = Steam()
When we call steam The extend function will modify the steam itself, while calling concatenate will return a new instance object without modifying the steam itself.
4. Essential difference
We can try to implement the two decorators of classmethod and staticmethod to see their essential differences:
class StaticMethod: def __init__(self, func): self.func = func def __get__(self, instance, owner): return self.func def __call__(self, *args, **kwargs): # New in Python 3.10 return self.func(*args, **kwargs) class ClassMethod: def __init__(self, func): self.func = func def __get__(self, instance, owner): return self.func.__get__(owner, type(owner)) class A: def normal(self, *args, **kwargs): print(f"normal({self=}, {args=}, {kwargs=})") @staticmethod def f1(*args, **kwargs): print(f"f1({args=}, {kwargs=})") @StaticMethod def f2(*args, **kwargs): print(f"f2({args=}, {kwargs=})") @classmethod def g1(cls, *args, **kwargs): print(f"g1({cls=}, {args=}, {kwargs=})") @ClassMethod def g2(cls, *args, **kwargs): print(f"g2({cls=}, {args=}, {kwargs=})") def staticmethod_example(): A.f1() A.f2() A().f1() A().f2() print(f'{A.f1=}') print(f'{A.f2=}') print(A().f1) print(A().f2) print(f'{type(A.f1)=}') print(f'{type(A.f2)=}') def main(): A.f1() A.f2() A().f1() A().f2() A.g1() A.g2() A().g1() A().g2() print(f'{A.f1=}') print(f'{A.f2=}') print(f'{A().f1=}') print(f'{A().f2=}') print(f'{type(A.f1)=}') print(f'{type(A.f2)=}') print(f'{A.g1=}') print(f'{A.g2=}') print(f'{A().g1=}') print(f'{A().g2=}') print(f'{type(A.g1)=}') print(f'{type(A.g2)=}') if __name__ == "__main__": main()
The above class staticmethod is equivalent to decorator staticmethod, and class classmethod is equivalent to decorator classmethod. The execution result of the code is as follows:

It can be seen that the functions of staticmethod and classmethod are the same as those of the standard library. It can also be seen that the difference between classmethod and staticmethod is that classmethod contains class information and can call the constructor of class, which has better expansibility in programming.
Last words
To answer the initial question of this article, why is classmethod more favored by the standard library? Because classmethod can replace static method, but not vice versa. In other words, where staticmethod is used, replace staticmethod with classmethod, and then add the first parameter cls to the function. The code called later can remain unchanged, but not vice versa. That is to say, classmethod has better compatibility.
On the other hand, classmethod can call the constructor of the class again internally, and generate a new instance without modifying the existing instance. It has stronger flexibility and scalability, so it is more favored. Of course, this is just my humble opinion. If you have different ideas, you can Message discussion Ha.