关于python:Python-如何正确使用静态方法和类方法

2次阅读

共计 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”还可支付大量学习材料。或是返回编程学习网,理解更多编程技术常识。

正文完
 0