python 装饰器(类装饰器和函数装饰器)

一、函数装饰器示例

def report1(text,rs):
    callnum = 0#定义一个变量,用于保存调用次数
    def decorator(fuct):
        #使用function.wraps装饰器,把相关的属性从fuct复制到inner中。
        # 否则被装饰的函数调用__name__将打印的是inner
        @wraps(fuct)
        def inner(*args, **kwargs):
            # 将callnum标记为自由变量,以便在内嵌函数中使用,否则会报错;
            # 如果使用的外部变量是引用类型如list,则不需要声明,前提是非赋值操作。
            nonlocal callnum
            callnum += 1
            try:
                fuct(*args, **kwargs)#执行原来的函数,如果原函数有return,需要将原函数执行结果进行return
                rs.append((text + str(callnum), fuct.__name__, 1, ''))#原函数未报错执行改语句,保存用例执行结果
            except Exception as e:
                rs.append((text + str(callnum), fuct.__name__, 0, str(e)[:100]))#保存原函数执行结果(捕获的异常)
                raise #向外抛出异常
        return inner #返回内部函数,取代被装饰的函数
    return decorator #返回装饰器

@report('',[])#带参的装饰器必须以调用函数的形式进行,即名称后面加上()
def name():
    print('--------------------')

二、类装饰器

class report:
    def __init__(self,text,rs):
        self.text = text
        self.rs = rs
    def __call__(self, fuct):#定义__call__函数,让类实例成为可调用对象
        callnum = 0
        @wraps(fuct)
        def decorator(*args, **kwargs):
            nonlocal callnum
            callnum += 1
            try:
                fuct(*args, **kwargs)
                self.rs.append((self.text + str(callnum), fuct.__name__, 1, ''))
            except Exception as e:
                self.rs.append((self.text + str(callnum), fuct.__name__, 0, str(e)[:100]))
                raise
          return decorator

你可能感兴趣的:(python 装饰器(类装饰器和函数装饰器))