类方法、静态方法和实例方法
一、实例方法
先定义一个输出日期的类Date,后面内容都是基于此类进行拓展。
class Date:
def __init__(self,year,month,day):
self.year=year
self.month=month
self.day=day
def __str__(self):
return "{year}/{month}/{day}".format(year=self.year,month=self.month,say=self.day)
if __name__ == "__main__":
new_day = Date(2018,12,30)
print(new_day) # 2018/12/30
普通情况下类内定义的都是实例方法,比如上述代码中的__init__()
和__str__()
都是实例方法。
比如在一开始的Date
类中再新定义一个实例方法tomorrow
。该方法使日期数加一(在这为了简单就不做日期的判断了)。
def tomorrow(self):
self.day += 1
if __name__ == "__main__":
new_day = Date(2018,12,30)
new_day.tomorrow() # python会自动转换成tomorrow(new_day)这种形式
print(new_day) # 2018/12/31
实例方法是针对实例进行操作,像self.变量+赋值符号
就变成了实例对象的变量,而修改类变量则要用类名.变量+赋值符号
。
二、静态方法
先引入这样一个场景,假设Date
类传入的字符串参数是2018-12-31
这个样子的。而我们一开始定义的传入参数是用逗号隔开的,所以肯定不行。
那为了达到这样的目的,先想到的最简单的办法就是用split
函数,将字符串处理一下,再放进去。
date_str = "2018-12-30"
year, month, day = tuple(data_str.split("-"))
# print(year,month,day) # 2018 12 30
new_day = Date(int(year),int(month),int(day))
print(new_day) # 2018/12/30
可以想到在Date
类中并没有提供可以将字符串转换成标准输入的方法。所以就有了自己先处理一下再输入的方法。
这种方法有一个很大的问题,就是每一次实例化Date
类时,都需要加上一段处理字符串的代码(即year, month, day = tuple(data_str.split("-"))
)。
但实际上我们可以把这种逻辑放到类中,也就是定义静态方法。
@staticmethod
def parse_from_string(data_str):
year, month, day = tuple(data_str.split("-"))
return Date(int(year),int(month),int(day))
在python
中静态方法不用接收self
。
因为在Date
类的命名空间中,所以要使用Date.parse_from_string()
进行调用
#用staticmethon完成初始化
new_day = Date.prase_from_string(date_str)
print(new_day) # 2018/12/30
此时代码就变得简洁了,而且还可以在静态方法中再增加新的逻辑。但静态方法的的缺点就是因为使用硬编码的方式,如果类名改为NewDate
,那么静态方法中返回的Date
也要变为NewDate
,类多的时候会很麻烦。
所以就有了Python中的类方法。
三、类方法
@classmethod
def from_string(cls,data_str):
year, month, day = tuple(data_str.split("-"))
return cls(int(year),int(month),int(day))
__init__(self)
传递进来的self
是指对象,而from_string()
传递进来的cls
是指类本身。所以此时return
的就与类名没有关系了。
#用classmethon完成初始化
new_day = Date.prase_from_string(date_str)
print(new_day) # 2018/12/30
那我们是不是觉得classmethod
就可以完全替代staticmethod
。
staticmethod
当然还有别的用处,我们再设想一个场景,判断字符串是否合法。这个用classmethod
也是可以的,但是多想一下,做判断这个逻辑并不用返回这个字符串对象,没有必要用classmethon
把cls
传递进来。
@staticmethod
def valid(data_str):
year, month, day = tuple(data_str.split("-"))
if int(year)>0 and (int(month)>0 and month<=12) and (int(day)>0 and int(day)<=31) #简单的逻辑,实际中判断是否合法不是这样的
return True
else:
return False
print(Date.valid_str("2018-12-32")) # False
小节
静态方法,类方法前边需要加一个装饰器