9-5在类中定义装饰器

来源:互联网 发布:在iphone编程 编辑:程序博客网 时间:2024/06/14 05:22
# -*- coding:utf-8 -*-"""实际案例:实现一个能将函数调用信息记录到日志的装饰器:1.把每次函数的调用时间,执行时间.调用次数写入日志.2.可以对被装饰函数分组,调用信息记录到不同日志.3.动态修改参数,比如日志格式.4.动态打开关闭日志输出功能解决方案:为了让装饰器在使用上更加灵活,可以把类的实例方法作为装饰器,此时在包裹函数中就可以持有实例对象,便于修改属性和拓展功能"""import loggingfrom time import localtime, time, strftime, sleepfrom random import choiceclass CallingInfo(object):    def __init__(self, name):      # name决定日志输出到那个文件当中        log = logging.getLogger(name)        log.setLevel(logging.INFO)  # 输出级别        fh = logging.FileHandler(name + '.log')        log.addHandler(fh)        log.info('Start'.center(50, '-'))   # - 占位:-----------Start-----------        self.log = log        self.formatter = '%(func)s -> [%(time)s - %(used)s - %(ncalls)s]'    def info(self, func):        def wrapper(*args, **kwargs):            wrapper.ncalls += 1            lt = localtime()            start = time()            res = func(*args, **kwargs)            used = time() - start            info = {}     # 构造字典            info['func'] = func.__name__            info['time'] = strftime('%x %X', lt)            info['used'] = used            info['ncalls'] = wrapper.ncalls            msg = self.formatter % info    # 用字典格式化self.formatter得到输出信息            self.log.info(msg)            return res        wrapper.ncalls = 0           # 将调用次数作为函数的属性,比较方便调用        return wrapper    def setFormatter(self, formatter):        self.formatter = formatter    def turnOn(self):        """降低级别"""        self.log.setLevel(logging.INFO)    def turnOff(self):        """抬高级别"""        self.log.setLevel(logging.WARN)cinfo1 = CallingInfo('mylog1')cinfo2 = CallingInfo('mylog2')cinfo1.setFormatter('%(func)s -> [%(time)s - %(ncalls)s]')cinfo2.turnOff()@cinfo1.infodef f():    print('in f')@cinfo1.infodef g():    print('in g')@cinfo2.infodef h():    print('in h')for _ in range(50):    choice([f, g, h])()                    # choice 的使用    sleep(choice([0.5, 1, 1.5]))
0 0