一、类的静态方法
被 @staticmethod 装饰过类的方法,被称为类的静态方法。类的普通方法变成静态方法之后,在调用时系统将不把类本身或对象本身作为实参赋给形参,在静态方法中引用类或对象的数据成员或方法,必须用“类名”或“对象名”这种硬编码的方式。例如:
class c01:
a=100
@ staticmethod
def fun01(x,y): print(x,y,c01.a)
c01.fun01(7,8) # 7 8 100
既然静态方法访问类或对象的数据成员或方法也必须用硬编码的方式,那与类外的函数不就没区别了吗?实际上,静态方法与类外的函数的确是没有多少区别。类的普通方法变成静态方法之后,基本上与类就切断了联系,静态方法之所以要放在类中,通常只是这个静态方法的主要功能与这个类相关。也就是说,静态方法放在类中,主要是有利于组织代码,有利于命名空间的整洁。例如在下例中,检查一个数值是否是合格的日期或月份的函数,是一个很一般函数,放在类里面和放在类外面都可以,但放在类里面显然便于管理:
class ymd():
def __init__(self, y=0, m=0, d=0): self.y=y;self.m=m;self.d=d;
def riqi(self):
return self.y+'年'+self.m+'月'+self.d+'日'
@classmethod
def riqi2(cls,x): y, m, d=map(str,x.split('-')); return cls(y,m,d)
@classmethod
def riqi3(cls,x): y, m, d=map(str,x.split('/')); return cls(y,m,d)
@ staticmethod
def chk_m(x):
if(x>12): print('Wrong Month:',x)
else: print('Right Month:',x)
@ staticmethod
def chk_d(x):
if(x>31): print('Wrong Day:',x)
else: print('Right Day:',x)
d01 = ymd('2020', '01', '01')
print(d01.riqi()) # 2020年01月01日
d02 = ymd.riqi2('2020-02-02')
print(d02.riqi()) # 2020年02月02日
d03 = ymd.riqi3('2020/03/03')
print(d03.riqi()) # 2020年03月03日
ymd.chk_m(6) # Right Month: 6
ymd.chk_m(26) # Wrong Month: 26
ymd.chk_d(6) # Right Day: 6
ymd.chk_d(26) # Right Day: 26
ymd.chk_d(36) # Wrong Day: 36
二、@property、@classmethod、@staticmethod 使用小结
1、从纯编程的角度看:
(1)不想接受任何额外参数的类的方法,可用 @property 或 property() 转变成类的属性,这样引用时很方便,小括号都可以不要。
(2)不想接受类对象这个实参,而只想接受类本身这个实参的类的方法,可用 @classmethod 装饰转变成类的类方法,这样操作类的数据成员和方法很方便,创建类的对象也很方便。
(3)既不想接受类对象这个实参,也不想接受类本身这个实参的类的方法,也就是,不想操作类或对象的数据成员和方法,仅想在类里面放一放的函数,可以用 @staticmethod 装饰转变成类的静态方法,这样函数定义时可以任意设置参数,省去对第一个形参的顾虑。
2、从应用的角度看:
(1)当需要保护某个私有成员时,可用 @property 或 property() 定义一个属性,然后通过这个属性来访问和操作那个需要保护的私有成员。
(2)当需要在创建对象前作些预处理的工作时,可用 @classmethod 定义一个类方法,然后在这个类方法中先进行预处理,最后创建对象,并将新创建的对象返回。
(3)当需要做些与类相关的工作,但又不需要引用类或对象的数据成员和方法时,可以在类中定义一个做相关工作的方法,然后用 @staticmethod 装饰,变成一个类的静态方法。
3、用 @property、@classmethod、@staticmethod 装饰,往往是为了使编程更便捷,而不是一定要这样做,不用它们进行装饰,使用普通的类的方法,通常也能达到同样的目的,但使用起来可能会稍微麻烦一些。