当前位置: 首页 > 后端技术 > Python

Python如何正确使用静态方法和类方法?

时间:2023-03-26 11:07:43 Python

最近有同学在后台问,什么时候用静态方法,什么时候用类方法。今天我们就来看看这两种方法的应用场景。首先定义一个普通类,里面全是普通的普通方法也叫实例方法类People:def__init__(self,name,age):self.name=nameself.age=agedefintroduce_myself(self):print(f'大家好,我的名字是:{self.name}')DEFADD_TWO_STRING_NUM(SELF,A,B):A_int=int(a)b_int=int(b)Returna_int+b_intdefcall_n_n_year(self,n):Age=sethd_two_num)print(f'{n}年后,我{age}岁')该类运行效果如下图所示:请注意该类中的add_two_string_num方法,它接受两个参数并将它们转换为int类型,然后相加并返回结果。这个过程很简单,但是它和People类有什么直接的关系吗?其实这个方法和这个类没有直接关系,我们甚至可以把它改成一个函数:defadd_two_string_num(a,b):a_int=int(a)b_int=int(b)returna_int+b_intclassPeople:def__init__(self,name,age):self.name=nameself.age=agedefintroduce_myself(self):print(f'大家好,我的名字是:{self.name}')defcalc_age_after_n_year(self,n):=ageadd_two_string_num(self.age,n)print(f'{n}年后,我{age}岁')kingname=People('kingname',20)kingname.introduce_myself()kingname.calc_age_after_n_year(10)结果与之前完全一样:我们可以说add_two_string_num函数是一个效用函数。效用函数接收参数并输出结果,与调用它的人或在何处调用无关。但是现在有一个尴尬的事情,这个函数只有People调用,其他地方都没有调用。单独放在其他地方是多余的,做成实例方法浪费了self参数。这时候我们可以使用静态方法::{self.name}')@staticmethoddefadd_two_string_num(a,b):a_int=int(a)urnb_intre=int(b)a_int+b_intdefcalc_age_after_n_year(self,n):age=People.add_two_string_num(self.age,n)print(f'{n}年后,我{age}岁')kingname=People('kingname',20)kingname.introduce_myself()kingname.calc_age_after_n_year(10)一句话总结:A静态方法是专用于某个类的工具函数。说完静态方法,再来说说类方法。什么时候应该使用类方法?在回答这个问题之前,先问大家一个问题,People类如何初始化为实例?你不觉得不容易吗,就一行代码:xxx=People('xxx',10)注意,你在初始化这个类的时候,一个一个传入参数。如果你用过顺丰发快递,你会发现在填写收件人的时候,有两种方式,一种方式和上面一样,一个一个填入参数。另一种方式,它给你一个输入框,你把一段包含姓名、地址、手机号码的文本粘贴进去,它会自动解析。所以,如果我现在给你一个字符串:我的名字:Qingnan,我的年龄:20,提取它。如何根据这个字符串生成People类的实例?这时候你可能会这样写:importrecontent='我的名字:青楠,我的年龄:20,提取出来'name=re.search('姓名:(.*?),',content)。group(1)age=re.search('Age:(\d+)',content).group(1)kingname=People(name,age)确实可以这样做,但是我可以让People类自动认识吗??事实上,这是可能的。有两种方法。一种方法是在__init__中多加几个参数,然后在初始化时从这些参数中解析出来。这个方法大家都知道,我就不说了。.再说第二种方法,就是使用类方法。我们只需要定义另一个类方法:importreclassPeople:def__init__(self,name,age):self.name=nameself.age=agedefintroduce_myself(self):print(f'大家好,我的名字是:{self.name}')@staticmethoddefadd_two_string_num(a,b):a_int=int(a)b_int=int(b)返回a_int+b_int@classmethoddeffrom_chinese_string(cls,句子):(re.name.名称:(.*?),',content).group(1)age=re.search('Age:(\d+)',content).group(1)returncls(name,age)defcalc_age_after_n_year(self,n):age=People.add_two_string_num(self.age,n)print(f'{n}年后,我{age}岁')content='我的名字:庆南,我的年龄:20,提取出来出来'kingname=People.from_chinese_string(content)kingname.introduce_myself()kingname.calc_age_after_n_year(10)运行效果如下图所示:类方法被装饰器@classmethod装饰,其第一个参数为隐式参数cls。这个参数实际上就是People类本身。这个隐式参数在我们调用类方法的时候是不需要传入的。在这个类方法中,相当于用People初始化一个实例,然后返回这个实例。这样做有什么好处?好处是我们根本不需要修改__init__,所以我们不需要修改代码中其他调用People类的地方。比如现在我想增加从英文句子中提取名字和年龄的功能,那么只需要再增加一个类方法:importreclassPeople:def__init__(self,name,age):self.name=nameself.age=agedefintroduce_myself(self):print(f'大家好,我的名字是:{self.name}')@staticmethoddefadd_two_string_num(a,b):a_int=int(a)urnb_intre=int(b)_+b_int@classmethoddeffrom_chinese_string(cls,sentence):name=re.search('name:(.*?),',content).group(1)age=re.search('age:(\d+)',content).group(1)返回cls(name,age)@classmethoddeffrom_english_string(cls,sentence):name=re.search('name:(.*?),',content).group(1)age=re.search('age:(\d+)',content).group(1)返回cls(name,age)defcalc_age_after_n_year(self,n):age=People.add_two_string_num(self.age,n)print(f'{n}年后,我{age}岁')content='我的名字:kinganme,我的年龄:15请提取'kingname=People.from_english_string(content)kingname.introduce_myself()kingname.calc_age_after_n_year(10)运行效果如下图所示:一句话总结:当你想使用工厂模式根据不同参数生成同一个类的不同对象时,你可以使用类方法实际上,如果你使用过Python自带的datetime模块,你会发现类方法无处不在:importdatetimenow=datetime.datetime.now()dt=datetime.datetime.fromtimestamp(1633691412)dt2=日期时间.日期时间。这段代码中的fromisoformat('2021-10-0819:10:05').now()、.fromtimestamp()和.fromisoformat()都是类方法。它们都返回datetime.datetime对象,区别在于它们是根据不同类型的输入参数生成的。以上就是本次分享的全部内容。觉得文章还不错的话,请关注公众号:Python编程学习圈,每日干货分享,发送“J”还能领取大量学习资料。或者去编程学习网了解更多编程技术知识。