案例:

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

需求:

  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. 第十六章:Python の Web开发基础(三) jQuery与Ajax

    本課主題 jQuery 介绍 Ajax 介绍 jQuery 介绍 选择器 jQuery 的选择器分不同的种类,主要目的是用来查找目标的 HTML 标签,方便对目标标签进行操作,比如找到 <li& ...

  2. CSS选择器:伪类(图文详解)

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 伪类(伪类选择器) 伪类:同一个标签,根据其不同的种状态,有不同的样式. ...

  3. 不要错过iost币的免费派发机会

    2013 年 ripple 币曾经进行免费派发,而现在瑞波币兑CNY价格最高曾经达到20元, 如果你错过了 ripple 币,就不要错过这次李笑来和徐小平等背书 iost 币的免费派发

  4. DAY5-小别-2018-1-15

    有两天没有写了,前天考完试出去浪了,惭愧自己没有学习:昨天,启程回家看完了循环内容的视频,晚上十点半火车到站,没抽出时间写了,还看了<黑客帝国>,有点小感触,人工智能的时代即将到来,我们该 ...

  5. 常见linux命令用法介绍

    su switch user 用途:用于用户之间的切换 格式: su - USERNAME切换用户后,同时切换到新用户的工作环境中 su USERNAME切换用户后,不改变原用户的工作目录,及其他环境 ...

  6. gitignore文件的作用

    早上上传文件的时候,发现有一些密钥不需要增加到版本库中,但是由于每次git status都会提示Untracked files ...并且这些文件并不需要一直提示,会占用相应的需要跟踪的文件位置,导致 ...

  7. d3 画地图终极自适应大小方案

    d3,v4以前用d3画地图的时候,为了让地图差不多正好画在容器的上下左右正中间,不得不慢慢的这样调: const projection = d3.geoMercator() .center([108. ...

  8. 初识DJango——Web框架

    一.Web框架 HTTP特点 1.简单快速:客户向服务器请求服务时,只需传送请求方法和路径.请求方法常用的有GET.HEAD.POST.每种方法规定了客户与服务器联系的类型不同. 由于HTTP协议简单 ...

  9. deeplearning.ai 神经网络和深度学习 week3 浅层神经网络 听课笔记

    1. 第i层网络 Z[i] = W[i]A[i-1] + B[i],A[i] = f[i](Z[i]). 其中, W[i]形状是n[i]*n[i-1],n[i]是第i层神经元的数量: A[i-1]是第 ...

  10. [51nod1291]Farmer

    用单调栈的话不严格的O(n^3)可以轻松艹过去,统计的时候要差分. 可以发现,对于一个单调栈里的元素,从它进栈到出栈都会重复类似的计算..再差分一波后就可以只在出栈的时候计算一下了. 具体的话看代码吧 ...