共计 4842 个字符,预计需要花费 13 分钟才能阅读完成。
最近有同学在后盾问,什么状况下应用静态方法,什么状况下应用类办法
明天咱们就来捋一下这两个办法的利用场景
首先,咱们来定义一个一般的类,外面都是一般的办法,一般办法又叫实例办法
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce_myself(self):
print(f'大家好,我叫: {self.name}')
def add_two_string_num(self, a, b):
a_int = int(a)
b_int = int(b)
return a_int + b_int
def calc_age_after_n_year(self, n):
age = self.add_two_string_num(self.age, n)
print(f'{n}年当前,我 {age} 岁')
这个类运行起来的成果如下图所示:
大家留神在这个类外面的办法 add_two_string_num
,它承受两个参数,并将他们转换为int
类型,而后相加并返回后果。这个过程非常简单,然而,它跟 People 这个类有什么间接关系吗?
其实这个办法跟这个类没有什么间接关系,咱们甚至把它改成函数都能够:
def add_two_string_num(a, b):
a_int = int(a)
b_int = int(b)
return a_int + b_int
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce_myself(self):
print(f'大家好,我叫: {self.name}')
def calc_age_after_n_year(self, n):
age = 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)
运行后果跟之前齐全一样:
咱们能够说,add_two_string_num
函数就是一个 工具函数
。工具函数接管参数,输入后果,齐全不关怀谁在调用他,也不关怀在哪里调用他。
但当初有一个比拟难堪的事件,这个函数,只有 People
在调用,其它中央都没有调用。独自把它放到其它中央又显得多余,弄成实例办法又节约了 self 参数,这个时候,咱们就能够用静态方法:
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce_myself(self):
print(f'大家好,我叫: {self.name}')
@staticmethod
def add_two_string_num(a, b):
a_int = int(a)
b_int = int(b)
return a_int + b_int
def calc_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)
一句话总结:静态方法就是某个类专用的工具函数。
说完了静态方法,咱们再说说类办法。什么状况下应该应用类办法呢?答复这个问题前,我先反诘你一个问题,怎么把 People
类初始化成一个实例?
你说这还不简略吗,一行代码就行了啊:
xxx = People('xxx', 10)
留神,这里你在初始化这个类的时候,你是一个一个参数传入进去的。如果你用过顺丰寄送快递,你就会发现,填写收件人的时候,有两种形式,一种形式就像下面这样,一个一个参数填进去。另一种形式,它给你一个输入框,你把一段蕴含姓名,地址,手机号的文字粘贴进去,它主动解析。
那么,如果我当初给你一个字符串:我的名字:青南,我的年龄:20,把它提取进去
。你怎么基于这个字符串生成 People 类的实例?
这个时候,你可能会这样写:
import re
content = '我的名字:青南,我的年龄:20,把它提取进去'
name = re.search('名字:(.*?),', content).group(1)
age = re.search('年龄:(\d+)', content).group(1)
kingname = People(name, age)
这样做的确能够,但我能不能让 People 这个类自动识别呢?其实是能够的,有两种办法,一种办法是在 __init__
外面多加几个参数,而后在初始化的时候,从这几个参数外面解析,这个办法大家都晓得,我就不多讲了。咱们来讲讲第二个办法,就是应用类办法。
咱们只须要再定义一个类办法:
import re
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce_myself(self):
print(f'大家好,我叫: {self.name}')
@staticmethod
def add_two_string_num(a, b):
a_int = int(a)
b_int = int(b)
return a_int + b_int
@classmethod
def from_chinese_string(cls, sentence):
name = re.search('名字:(.*?),', content).group(1)
age = re.search('年龄:(\d+)', content).group(1)
return cls(name, age)
def calc_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
类的中央。例如当初我又想减少从英文句子外面提取名字和年龄的性能,那么只须要再增加一个类办法就能够了:
import re
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce_myself(self):
print(f'大家好,我叫: {self.name}')
@staticmethod
def add_two_string_num(a, b):
a_int = int(a)
b_int = int(b)
return a_int + b_int
@classmethod
def from_chinese_string(cls, sentence):
name = re.search('名字:(.*?),', content).group(1)
age = re.search('年龄:(\d+)', content).group(1)
return cls(name, age)
@classmethod
def from_english_string(cls, sentence):
name = re.search('name: (.*?),', content).group(1)
age = re.search('age: (\d+)', content).group(1)
return cls(name, age)
def calc_age_after_n_year(self, n):
age = People.add_two_string_num(self.age, n)
print(f'{n}年当前,我 {age} 岁')
content = 'my name: kinganme, my age: 15 please extract them'
kingname = People.from_english_string(content)
kingname.introduce_myself()
kingname.calc_age_after_n_year(10)
运行成果如下图所示:
一句话总结:当你想应用工厂模式,依据不同的参数生成同一个类的不同对象的时候,就能够应用类办法。
其实如果大家应用过 Python 自带的 datetime
模块,你就会发现类办法无处不在:
import datetime
now = datetime.datetime.now()
dt = datetime.datetime.fromtimestamp(1633691412)
dt2 = datetime.datetime.fromisoformat('2021-10-08 19:10:05')
这段代码外面的 .now()
、.fromtimestamp()
和 .fromisoformat()
,都是类办法。他们最终返回的都是 datetime.datetime
对象,区别在于他们是依据不同类型的输出参数生成的。
以上就是本次分享的所有内容,如果你感觉文章还不错,欢送关注公众号:Python 编程学习圈,每日干货分享,发送“J”还可支付大量学习材料。或是返回编程学习网,理解更多编程技术常识。