首先,staticmethod和classmethod裝飾器是通過非資料描述符實現的。用法簡單,這裡就不細說了。

這裡主要分析一下staticmethod和classmethod是如何通過描述符實現的。

from functools import partial

class StaticMethod:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):
        return self.func

class ClassMethod:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):
        # 由於類方法需要傳遞cls作為第一個位置引數,這裡使用偏函式固定cls為第一個位置引數,並返回函式
        return partial(self.func, owner)

class A:
    @StaticMethod  # foo = StaticMethod(foo)得到一個描述符例項
    def foo():
        print('static method called')

    @ClassMethod  # bar = ClassMethod(bar)得到一個描述符例項
    def bar(cls):
        print('class method called')

a = A()

a.foo()  # 訪問描述符例項a.foo觸發呼叫__get__方法,然後呼叫__get__方法的返回值
# static method called

a.bar()
# class method called

如果看過了上篇property,相比之下,這個就簡單了不少。
這裡用到了偏函式、裝飾器以及面向物件的知識,希望你能得心應手。

參考:
https://docs.python.org/3/library/functions.html#staticmethod
https://docs.python.org/3/library/functions.html#classmethod