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 也是常用的装饰类函数的装饰器,其作用是可以直接使用实例名.函数名来进行调用函数,不需要末尾加()了。