案例:

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

需求:

  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. Android开发之漫漫长途 X——Android序列化

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  2. 总结Oracle8i 的UNDO表空间损坏(ORA-01092及ORA-00600【4193】)情况下的数据库不完全恢复的经历

    服务器断电重启导致备份生产环境的恢复目录库无法进行启动,提示Ora-01092例程终止.强行断开连接 查看跟踪日志: Wed Jan 10 08:41:37 2018 Errors in file d ...

  3. PE文件详解(五)

    在前面几节中经常提到相对虚拟地址RVA,在这篇博客中主要说明这个概念.本来是想接着转载小甲鱼的,但是我自己根据这篇文章和他的视频来学习的时候,发现在RVA与文件的相对偏移地址进行转化的时候,那块我看不 ...

  4. 运用OpenMP提速图像处理速度

    一.算法测试 // openmptest的测试程序#include "stdafx.h"void Test(int n){    for (int i=0;i<10000;i ...

  5. 常用Atom插件列表

    1.simplified-chinese-menu Atom的简体中文语言包,完整汉化,兼容所有已发布的版本Atom. 2.tree-view-finder 左边菜单栏显示方式,类似Mac OS下的f ...

  6. 浏览器history操作实现一些功能

    返回拦截 功能:从广告进入到落地页后,给history增加一个页面,拦截返回动作 主要用到的是h5中的history对象,使用了pushState,和replaceState来操作. 并且加入了一些条 ...

  7. keynote 代码高亮

    brew install highlight (同时会安装 Lua 和 Boost) highlight -K 18 -s Vampire -u 'utf-8' -O rtf test.html | ...

  8. 常用SQL语句集合

    一.数据定义 1.创建新数据库:CREATE DATABASE database_name2.创建新表:CREATE TABLE table_name (column_name datatype,co ...

  9. Go并发模式:管道与取消

    关键字:Go语言,管道,取消机制,并发,sync.WaitGroup,包引用,通道,defer,select GO并发模式:管道与取消 简介 Go的并发能力可以使构建一个流数据管道变得非常容易,并且可 ...

  10. Git分支-分支简介

    源地址:https://git-scm.com/book/zh/ch3-1.html 几乎所有的版本控制系统都以某种形式支持分支. 使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线 ...