Python类定义中的@classmethod(类方法)和@staticmethod(静态方法)的使用

  之前的一篇博文详细讲解了什么函数装饰器(Python迭代器、生成器、装饰器的使用)。在类的定义中,我们也常常见到装饰器的使用,并且最常用的就是@classmethod,@staticmethod来装饰我们自定义类的函数(方法),这两个内置的装饰器是什么作用呢?

  在讲解这两种方法前我们需要只要,一般我们在类当中定义的方法都是实例方法,定义中都需要带有self关键字,要使用实例方法,必须先把我们的类实例化才能使用。比如下面的个Dog类中的name方法。

class Dog():
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def dogname(self):
        print("我是一只狗,名叫{}".format(self.name))

dog1 = Dog("阿黄", 12)

  如果要使用实例方法dogname(),我们只能采用dog1.dogname()才能够使用。实例方法可以访问实例变量、类变量,使用时必须通过实例名来调用。

1、类方法(@classmethod)

  什么叫做类方法呢?只要是在定义函数的时候在前面加上@classmethod那么接下来定义的这个函数就被称为类方法。

class Dog():
    dog_dict = {"大狗":12, "二狗":11, "三狗":20}  # 定义了一个类变量(一个字典),表示大狗有12只,二狗有11只,三狗有20只

    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def dogname(self):
        print("我是一只狗,名叫{}".format(self.name))

    @classmethod
    def dog_number(cls):
        number = 0 
        for item in cls.dog_dict.items():
            number += item[1]
        print('总共有{}只狗'.format(number))

    

dog1 = Dog("阿黄", 12)
dog2 = Dog("二黄", 7)
dog1.dog_number()
Dog.dog_number()

  执行结果:

  类方法不是因为具体的哪个实例而改变,因此在定义时必须使用cls(类变量)作为第一个参数(大家可以看成self的作用,只是它表示的是一个类)。既然这个方法是类方法,那我们自然可以采用类名.dog_number()来进行调用,也可以采用实例名.dog_number()来进行调用。类方法是可以访问类变量,当然也可以访问实例变量(不过需要传入参数self,并且在使用时需要把实例名传入函数中)。

2、静态方法(@staticmethod)

  同样的在定义函数的时候在前面加上@staticmethod那么接下来定义的这个函数就被称为静态方法,静态方法不要求你强制传入任何参数(实例方法必须传入slef,类方法必须传入cls),因此这个函数对类变量和实例变量都是一无所知,你需要自己传入参数才能使用。调用的时候,可以使用实例名.方法名调用,或者类名.方法名调用。看例子

class Dog():
    dog_dict = {"大狗":12, "二狗":11, "三狗":20}  # 定义了一个类变量(一个字典),表示大狗有12只,二狗有11只,三狗有20只

    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def dogname(self):
        print("我是一只狗,名叫{}".format(self.name))

    @classmethod
    def dog_number(cls):
        number = 0 
        for item in cls.dog_dict.items():
            number += item[1]
        print('总共有{}只狗'.format(number))

    @staticmethod
    def total_age(dogs):
        '''
        传入一个Dog实例的list,并计算这些狗的总年龄
        '''
        total = 0
        for dog in dogs:
            total += dog.age
        return total


dog1 = Dog("阿黄", 12)
dog2 = Dog("二黄", 7)
print(dog1.total_age([dog1, dog2]))

  

3、额外知识

  1、类变量:是所有实例共享的,专属于这个类的,换句话说只要当前这个实例时属于A类,那么该实例就能使用A类的所有类变量。访问类变量得分情况,如果是在类方法中访问类变量,那么是使用 cls.类变量名 ;如果是在实例方法中访问类变量,使用 self.类变量名 。

  2、除了常用的@classmethod和@staticmethod是常用的自定义类函数的装饰器,还有@property 也是常用的装饰类函数的装饰器,其作用是可以直接使用实例名.函数名来进行调用函数,不需要末尾加()了。

 

参考网页:

Python小技巧#9:实例方法,类方法,静态方法的区别?_哔哩哔哩_bilibili

posted @ 2021-12-30 17:42  Circle_Wang  阅读(442)  评论(0编辑  收藏  举报