案例:

实现一个能将函数调用信息记录到日志的装饰器

需求:

  1. 把每次函数的调用时间,执行时间,调用次数写入日志
  2. 可以对被装饰函数分组,调用信息记录到不同日志
  3. 动态修改参数,比如日志格式
  4. 动态打开关闭日志输出功能

如何解决这个问题?

  为了装饰器的灵活性,定义一个装饰类,把这个类的实例方法当做装饰器,在类中装饰器方法持有实例对象,便于修改属性和扩展功能

#!/usr/bin/python3

import logging
from time import time, strftime, localtime, sleep
from random import choice
from functools import wraps

class ToLog():
    def __init__(self, name):
        log = logging.getLogger(name)
        log.setLevel(logging.INFO)
        # 日志保存文件名字
        file_name = logging.FileHandler(name + '.log')
        # 添加日志文件
        log.addHandler(file_name)
        # 日志格式
        log.info('start'.center(50, '-'))
        self.log = log
        self.temp = '%(func)s -> [%(start_time)s - %(used_time)s - %(naclls)s]'

    def go_log(self, func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 函数每调用一次加1
            wrapper.naclls += 1

            start_time = time()
            res = func(*args, **kwargs)
            used_time = time() - start_time

            info = {}
            info['func'] = func.__name__
            info['start_time'] = start_time
            info['used_time'] = used_time
            info['naclls'] = wrapper.naclls

            msg = self.temp % info
            # 把日志按格式写入文件
            self.log.info(msg)

            return res

        # 初始化调用次数参数
        wrapper.naclls = 0

        return wrapper

    # 重新定义日志记录模版
    def set_log_temp(self, temp):
        self.temp = temp

    # 关闭日志功能
    def log_off(self):
        self.log.setLevel(logging.WARN)

    # 打开日志功能
    def log_on(self):
        self.log.setLevel(logging.INFO)

# 实例化出两个装饰器对象
log_one = ToLog('one')
log_two = ToLog('two')

# 修改实例2的日志模版,去掉执行时间
log_two.set_log_temp('%(func)s -> [%(start_time)s - %(naclls)s]')

# 关闭log_two中记录日志功能
log_two.log_off()

@log_one.go_log
def func_one():
    print('one')

@log_one.go_log
def func_two():
    print('two')

@log_two.go_log
def func_three():
    print('three')

if __name__ == '__main__':
    for _ in range(50):
        choice([func_one, func_two, func_three])()
        sleep(choice([0.5, 1, 1.5]))

  

python_如何定义装饰器类?的更多相关文章

  1. day20-Python运维开发基础(装饰器 / 类中的方法 / 类的方法变属性)

    1. 装饰器 / 类中的方法 / 类的方法变属性 # ### 装饰器 """ 定义:装饰器用于拓展原来函数功能的一种语法,返回新函数替换旧函数 优点:在不更改原函数代码的 ...

  2. python基础--定义装饰器(内置装饰器)

    装饰器的定义: 装饰器本质上就是一个python函数,它可以让其它函数在不需要做任何代码改动的前提下增加额外的功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景中,比如-- >插入 ...

  3. python_如何修改装饰器中参数?

    案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改t ...

  4. python装饰器类

    from functools import wraps class logit(object): def __init__(self, logger): self.logger = logger de ...

  5. Python装饰器实现几类验证功能做法

    最近新需求来了,要给系统增加几个资源权限.尽量减少代码的改动和程序的复杂程度.所以还是使用装饰器比较科学 之前用了一些登录验证的现成装饰器模块.然后仿写一些用户管理部分的权限装饰器.比如下面这种 de ...

  6. 基于TypeScript装饰器定义Express RESTful 服务

    前言 本文主要讲解如何使用TypeScript装饰器定义Express路由.文中出现的代码经过简化不能直接运行,完整代码的请戳:https://github.com/WinfredWang/expre ...

  7. 11.python描述符---类的装饰器---@property

    描述符1.描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()这三个内置方法中的一个,描述符也被称为描述符协议(1):__ ...

  8. Python之路(第二十八篇) 面向对象进阶:类的装饰器、元类

    一.类的装饰器 类作为一个对象,也可以被装饰. 例子 def wrap(obj): print("装饰器-----") obj.x = 1 obj.y = 3 obj.z = 5 ...

  9. Python全栈day28(类的装饰器)

    类是一个对象也可以像函数一样加装饰器 类的装饰器.py def deco(obj): print('======',obj) obj.x=1 obj.y=2 obj.z=3 return obj # ...

随机推荐

  1. Git知识总览(二) git常用命令概览

    上篇博客我们从 git clone 和 git status 两个命令开始,引出了一系列的git操作命令, 请参见:<Git知识总览(一) 从 git clone 和 git status 谈起 ...

  2. linux下安装运行LoadrGenerator

    注:在LoadGenerator的安装使用的过程,涉及到了shell变量与环境变量.用户使用的当前shell.创建用户等一系列的linux操作系统的问题,关注我后续的博客,会为大家继续讲解这些问题. ...

  3. Java学习笔记20(String类应用、StringBuffer类、StringBuilder类)

    1.获取指定字符串中大小写和数字的个数: package demo; public class StringTest { public static void main(String[] args) ...

  4. Twisted使用和scrapy源码剖析

    1.Twisted是用Python实现的基于事件驱动的网络引擎框架. 事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定.它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的 ...

  5. 0.python class

    http://pythonprogramminglanguage.com/ 什么是python? python是一款让你工作比起用其他语言更快的编程语言.老练的程序员用其他的语言会比用python更顺 ...

  6. C#学习笔记-工厂模式

    题目:计算器 解析:工厂方法(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类. 定义运算类: class Operation { ; ; public doubl ...

  7. 一个通用的Makefile(二)

    1.各级子目录的Makefile: obj-y += file.o obj-y += subdir/ “obj-y += file.o” 表示把当前目录下的file.c编进程序里. “obj-y += ...

  8. poj 3294

    Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12688   Accepted: 3552 Descr ...

  9. Codeforces 839E Mother of Dragons【__builtin_popcount()的使用】

    E. Mother of Dragons time limit per test:2 seconds memory limit per test:256 megabytes input:standar ...

  10. 51nod1649- 齐头并进-最短路

    1649 齐头并进 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 在一个叫奥斯汀的城市,有n个小镇(从1到n编号),这些小镇通过 ...