classmethod、staticmethod的使用场景与区别

实例变量与类变量

在定义类的过程中,可以通过如下的例子定义类变量与实例变量。实例化之后,所有的实例对象都共享类变量,但是不共享实例变量。

class Demo:
    a = 1
    def __init__(self, x):
        self.x = x

demo_a = Demo("demo_a")
demo_b = Demo("demo_b")

classmethod 与 staticmethod

清楚理解实例变量与类变量的区别后,我们再看 classmethod 与 staticmethod。
classmethod 与 staticmethod 在python中代表类方法与静态方法,通过使用装饰器修改对应的方法类型。如下代码所示

class MethodsDemo:
    param_a = 0
    def normal_demo(self, x):
        """
        普通方法
        :return:
        """
        self.param_a = x

    @classmethod
    def classmethod_demo(cls, x):
        """
        类方法,第一个参数需要改为cls
        :return:
        """
        cls.param_a = x

    @staticmethod
    def static_demo(x):
        """
        静态方法
        :return:
        """
        print("静态方法")


当然,这只是他们最浅层的区别,接下来会从,定义、调用、使用场景这三个方面去仔细分析这三者之间的异同

定义

  • classmethod

定义一个类方法,除了需要使用classmethod装饰器之外。python规范要求其方法的原本的第一个参数self 也需改为cls,其实这只是python要求的命名规范,只要使用了装饰器,名称不改也是可以的。

  • staticmethod

定义一个静态方法,需要删除原本存在的self形参,就像一个普通的函数一样

调用

  • classmethod
    既可以通过 类名.方法名() 也可以通过 实例名.方法名() 调用, 建议使用 类名.方法名() 直接调用
    demo = MethodsDemo()
    demo.classmethod_demo(2)
    MethodsDemo.classmethod_demo(3)
  • staticmethod
    既可以通过 类名.方法名() 也可以通过 实例名.方法名() 调用, 建议使用 类名.方法名() 直接调用
  • 普通方法
    只能通过 实例名.方法名() 调用

使用场景

通过上面的方法可能难以感受到这两个装饰器的好用之处

  • classmethod
    需要修改类变量的场景

  • staticmethod
    无需类或实例参与

  • 普通方法
    方法内部涉及到实例对象属性的操作

总结

名称 定义 调用 关键字 使用场景
classmethod 至少需要一个cls参数 类名.方法名() 或者实例名.方法名() @classmethod 如果需要对类属性,即静态变量进行限制性操作
staticmethod 无默认参数 类名.方法名() 或者实例名.方法名() @staticmethod 无需类或实例参与
普通方法 至少需要一个参数self 实例名.方法名() 方法内部涉及到实例对象属性的操作