Python 测开27期 - WL - 学习笔记 - python 装饰器

python 装饰器

python 内置装饰器

  • classmethod:类方法
  • statucmethod:静态方法
    ** 不用实例化,直接调用
    ** 提升代码可读性

普通方法

  • 定义:第一个参数为self,代表实例本身
  • 调用:要有实例化的过程,通过 实例对象.方法名 调用

类方法

  • 定义
    ** 使用@classmethod装饰器,第一个参数为类本身,所以通常使用cls命名做区分(不强制)
    ** 在类内可以直接使用类方法或类变量,无法直接使用实例变量或方法
  • 调用
    ** 无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
    ** 在类方法内,不可以直接调用实例方法和实例变量,但是可以直接调用类变量和类方法
    ** 在调用过程中,类和和实例都可以直接调用类方法
    image
'''类方法'''
# 定义
class Hunmmer:
    you = 'sak'
    @classmethod
    def stu(cls):
        print('这个一个有装饰器的方法',cls.you)
    def tea(self):
        print((f'这是第二个方法:{Hunmmer.you}'))
    @classmethod
    def stu2(cls):
        print('这个一个有装饰器的方法2',cls.you)
# 调用
Hunmmer.stu() # 结果是: 这个一个有装饰器的方法 sak
aa = Hunmmer()
aa.tea() # 结果是:这是第二个方法:sak
aa.stu2() # 结果是: 这个一个有装饰器的方法2 sak

静态方法

  • 定义
    ** 使用@statycmethod 装饰器,没有和类本身有关的参数
    ** 无法直接使用任何类变量、类方法或者实例方法、实例变量
    ** 更像一个函数
  • 调用
    ** 无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
    image
'''类方法'''
# 定义
class Hunmmer:
    you = 'sak'
    @staticmethod
    def xcc(a):
        print(f'这个一个有解释器的静态方法:{Hunmmer.you}+{a}+{a}+{a}+{a}+{a}')
# 调用
aa = Hunmmer()
aa.xcc('play')# 结果是:这个一个有解释器的静态方法:sak+play+play+play+play+play
Hunmmer.xcc('s') # 结果是:这个一个有解释器的静态方法:sak+s+s+s+s+s

区别

名称 定义 调用 关键字 使用场景
普通方法 至少需要一个参数self 实例名.方法名() 方法内部涉及到实例对象属性的操作
类方法 至少需要一个cls参数 类名.方法名()或者实例名.方法名() @classmethod 如果需要对类属性,即静态变量进行限制性操作
静态方法 无默认参数 类名.方法名()或者实例名.方法名() @statucmethod 无需类或实例参与

实际案例1

  • 代码实现的需求是格式化输出时间
  • 若需求变更,输入年、月、日没法保证统一格式,可能是json,可能是其他格式字符串,在不修改构造函数的情况下,如何更改代码
class DateFormat:
    def __init__(self, year=0, month=0, day=0):
        self.year = year
        self.month = month
        self.day = day

    def out_date(self):
        return f'输入的时间为{self.year}年,{self.month}月,{self.day}天'

    @classmethod
    def json_date(cls, jsondate):
        '''要求输入一个字典格式的内容,返回year,month,day格式'''
        year, month, day = jsondate["year"], jsondate["month"], jsondate["day"]
        return cls(year, month, day)

    @classmethod
    def str_date(cls, srr):
        '''要求输入一个字符串格式的内容,'''
        ww = list(srr)
        year = ww[0] + ww[1] + ww[2] + ww[3]
        if len(ww) == 6:
            month, day = ww[4], ww[5]
        elif len(ww) == 8:
            month, day = ww[4] + ww[5], ww[6] + ww[7]
        elif len(ww) == 7:
            aa = ww[4] + ww[5]
            if int(aa) > 20:
                month = ww[4]
                day = ww[5] + ww[6]
            else:
                month = aa
                day = ww[6]
        return cls(year, month, day)

# 初始化格式
year, month, day = 2017, 7, 2
demo = DateFormat(year, month, day)
print(demo.out_date())  # 结果是: 输入的时间为2017年,7月,2天
# json格式
aa = {"year": 2022, "month": 11, "day": 3}
# 使用json格式化,生成想要的日期信息,返回DateFormat实例
dee = DateFormat.json_date(aa)
print(dee.out_date())  # 结果是: 输入的时间为2022年,11月,3天
# 字符串格式
bb = ['201991', '2020913', '2020104', '20201130']
for i in range(0, len(bb)):
    der = DateFormat.str_date(bb[i])
    print(der.out_date())
''' # 结果为
输入的时间为2019年,9月,1天
输入的时间为2020年,9月,13天
输入的时间为2020年,10月,4天
输入的时间为2020年,11月,30天
'''

实际案例2 - 静态方法案例

  • 此方法没有任何和实例、类相关的部分,可以作为一个独立函数使用
  • 某些场景下,从业务逻辑来说又属于类的一部分
  • 例子:简单工厂法
'''多轮比赛,每轮由2个不同方对战,'''
class Game:
    def __init__(self, one, two):
        self.one = one
        self.two = two
    def fight(self):
        print(f"本轮比赛由{self.one}和{self.two}对战")
    @staticmethod
    def start():
        print('游戏开始')
    @staticmethod
    def end():
        print('游戏结束')
Game.start()  # 结果是: 游戏开始
game1 = Game('保罗', '侏罗纪')
game2 = Game('鳄鱼', '鲨鱼')
game1.fight()  # 结果是: 本轮比赛由保罗和侏罗纪对战
game2.fight()  # 结果是: 本轮比赛由鳄鱼和鲨鱼对战
Game.end()  # 结果是: 游戏结束