Python装饰器的点点滴滴

43次阅读

共计 2120 个字符,预计需要花费 6 分钟才能阅读完成。

今天在写校验时间的代码时被要求用装饰器,我看了看我已经写好的代码

class StartDeploy(object):
    @classmethod
    def is_ban_time(cls):
        now_time = datetime.now().time()
        time_list = db.get_list('ACTIVITY_TIME:CAN NOT DEPOLY')
        if time_list:
            for time_str in time_list:
                _,start_time, end_time = time_str.split(',')
                start_time = datetime.strptime(start_time,'%H:%M:%S').time()
                end_time = datetime.strptime(end_time,'%H:%M:%S').time()
                # 比较时间
                if start_time <= now_time <= end_time:
                    return True
        return False

    @classmethod
    def start_deploy(cls):
        flag = True
        if cls.is_ban_time():
            while flag:
                input_value = raw_input("当前时间在禁止上线时间内,是否强制上线 (y/n):")
                if input_value.lower().split() == 'y':
                    flag = False
                elif input_value.lower().split() == 'n':
                    return False
        return True

心想装饰器确实是个不错的选择,不过我这个类有没有办法改成装饰器呢?我记得我以前看过一本书叫 Effect Python 提到过类装饰器,但具体怎么实现不会,今天就试试吧,也不想改成函数实现的装饰器了。

首先,类初始化一个对象要经过两步

  1. 执行__new__构造方法构造一个 cls 对象
  2. 执行__init__初始化一个 self 对象

也就是说在类的对象创建完成之前,通过重写以上两个方法我们可以干预它的创建过程

这有什么用呢?
我们可以在初始化对象的时候,将需要被装饰的函数传进来

class StartDeploy(object):
    
    def __init__(self, func):
        self.__func = func
        
def func():
    print('in func')

好,那么我们得在执行 func 之前进行时间校验,有没有办法去控制执行顺序?
在 python 中有许多魔法方法,包括下面这个:

    def __call__(self, *args, **kwargs):
        pass

在调用某个对象的方法时,__call__是调用的入口,即我们可以在执行任意一个对象方法之前,做一些操作,下面有个例子

class deco:
    def __init__(self, func):
        self.__func = func
    def w(self):
        print('in w')
    def printf(self):
        print('in printf')
        self.w()
    def __call__(self, *args, **kwargs):
        self.printf()
        self.__func()

@deco
def ceshi():
    print('in func')

ceshi()


所以基于以上特性,我们的类装饰器也就完成了

class StartDeploy(object):

    def __init__(self, func):
        self.__func = func

    def __call__(self, *args, **kwargs):
        if not self.start_deploy():
            return 
        self.__func()

    @classmethod
    def is_ban_time(cls):
        now_time = datetime.now().time()
        time_list = db.get_list('ACTIVITY_TIME:CAN NOT DEPOLY')
        if time_list:
            for time_str in time_list:
                _,start_time, end_time = time_str.split(',')
                start_time = datetime.strptime(start_time,'%H:%M:%S').time()
                end_time = datetime.strptime(end_time,'%H:%M:%S').time()
                # 比较时间
                if start_time <= now_time <= end_time:
                    return True
        return False

    @classmethod
    def start_deploy(cls):
        flag = True
        if cls.is_ban_time():
            while flag:
                input_value = raw_input("当前时间在禁止上线时间内,是否强制上线 (y/n):")
                if input_value.lower().split() == 'y':
                    flag = False
                elif input_value.lower().split() == 'n':
                    return False
        return True

装饰器相关的内容还挺多的,以后会慢慢更新

  1. 带参数的装饰器
  2. 多个装饰器嵌套的执行顺序
  3. 给类添加装饰器
  4. 闭包的概念

正文完
 0