装饰器模式

此前的文章中我们介绍过装饰器模式:

装饰器模式中具体的 Decorator 实现类通过将对组建的请求转发给被装饰的对象,并在转发前后执行一些额外的动作来修改原有的部分行为,实现增强 Component 对象中被请求方法的目的

装饰器模式是一种十分灵活的,可以动态添加和分离额外操作的设计模式,python 中的装饰器正是因为这个模式而得名,也是实现这个设计模式的得力工具

python 装饰器实现自动监控

装饰器模式的一个典型的应用场景就是对所有需要被监控的方法实现无差别的自动日志打印和监控上报的一些统计功能

下面的例子展示了函数执行时间的自动打印:

import time

import functiontools

import logging

def clock(func):

@functools.wraps(func)

def clocked(*args):

t0 = time.perf_counter()

result = func(*args)

elapsed = time.perf_counter() - t0

name = func.__name__

arg_str = ', '.join(repr(arg) for arg in args)

logging.info('[%0.8fs] %s(%s) -> %r' % (elapsed, name, arg_str, result))

return result

return clocked

上面的例子中,通过装饰器与闭包,实现了对 func 的增强,通过装饰器 clock,自动在 log 中打印了方法的执行时间

我们定义函数:

@clock

def snooze(seconds):

time.sleep(seconds)

return seconds

if __name__ == '__main__':

print(snooze(.123))

打印出了:[0.12405610s] snooze(.123) -> 0.123

0.123

functools.wraps

functools.wraps 是标准库中的一个装饰器,他把相关的属性从 func 复制到 clocked 中,从而让装饰器的外部表现与被装饰函数的表现林亮一直

监控优化 -- 增加参数

很多时候,我们需要在装饰器上传递一些参数,以实现不同场景的定制化需求,例如有些时候我们希望打印出全部参数、返回值,有些时候需要在发生异常时隐藏异常,返回预设的默认值等

了解了装饰器的原理以后,包含参数的装饰器就很容易写出来,事实上,无论嵌套多少层,只要记得开始的时候我们提到的装饰器的原理,就都不难理解了

import inspect

import logging

import time

import uuid

from functools import wraps

def report(project=None, type=None, name=None, raise_exception=True, result=None, paramslog=False, returnlog=False):

def decorator(func):

@wraps(func)

def wrapper(*arg, **kvargs):

cattype = type

if cattype is None:

cattype = inspect.getfile(func)

if project is not None:

cattype = '[:: ' + project + ' ::] ' + cattype

catname = name if name is not None else func.__name__

randid = str(uuid.uuid1())

if paramslog:

logging.info('<%s::%s> [%s] PARAMS: %r; %r' % (cattype, catname, randid, arg, kvargs))

try:

t0 = time.perf_counter()

res = func(*arg, **kvargs)

elapsed = time.perf_counter() - t0

if returnlog:

logging.info('<%s::%s> [%s;%0.8fs] RESULT: %r' % (cattype, catname, randid, elapsed, res))

return res

except Exception as e:

logging.error('<%s::%s> [%s] ERROR: %r' % (cattype, catname, randid, e), exc_info=True)

if raise_exception:

raise e

else:

return result

return wrapper

return decorator

python装饰器原理-python 中的装饰器及其原理相关推荐

  1. webpack 中的加载器简介||webpack 中加载器的基本使用——1. 打包处理 css 文件 2. 打包处理 less 文件 3.打包处理 scss 文件

    webpack 中的加载器 1. 通过 loader 打包非 js 模块 在实际开发过程中,webpack 默认只能打包处理以 .js 后缀名结尾的模块,其他非 .js 后缀名结尾的模块, webpa ...

  2. java8收集器,Java 8中的收集器collectionAndThen()方法

    collectingAndThen()Java Collectors类中的方法使Collector适应于执行其他完成转换.它返回执行下游收集器动作的收集器,然后执行附加的结束步骤. 语法如下.stat ...

  3. java web 过滤器 拦截器 监听器_Java中的拦截器和过滤器,可不是同一个东西

    过滤器(Filter) 过滤器就如上面的水质过滤器一样,把管道中的水进行一遍过滤再使用.过滤器基于filter接口中的doFilter回调函数,主要的用途是设置字符集.控制权限.控制转向.做一些业务逻 ...

  4. java 反复器_java集合类中的枚举器(反复器)

    在任何集合类中,必须通过某种方法在其中置入对象,再用另一种方法从中取得对象.毕竟,容纳各种各样的对象正是集合的首要任务.在Vector中,addElement()便是我们插入对象采用的方法,而elem ...

  5. android节操播放器回调,Android中节操播放器JieCaoVideoPlayer使用

    ##效果 ##使用 即便是自定义UI,或者对Library有过修改,也是这五步骤来使用播放器. ####1.添加类库 compile 'cn.jzvd:jiaozivideoplayer:6.0.0' ...

  6. java web 嵌套播放器_网页中嵌套视频播放器

    刚做完一个项目,其中有个视频播放的,其实网上的代码都没有错,但感觉不详细,特别是播放文件的路径,有本地的,有当前项目中的,有网络上的,网上很多,但没有一个说明是哪个路径,这里,经过本人测试,不多说了, ...

  7. 计算机晶体管怎么工作原理,CPU中的晶体管的工作原理?

    描述 CPU的产生 在了解CPU工作原理之前,我们先简单谈谈CPU是如何生产出来的.CPU是在特别纯净的硅材料上制造的.一个CPU芯片包含上百万个精巧的晶体管.人们在一块指甲盖大小的硅片上,用化学的方 ...

  8. impinj固定式阅读器数据解析中Rfid筛选器实现

    在做物联网仓库管理中用到RFID标签进行盘点和出库扫描检查,其中在仓库门口的impinj固定式阅读器对进出的货物进行检测,在读取rfid时候需要对epc标签进行过滤,实现2个过滤器,第一个是正则过滤, ...

  9. android调用文件管理器回调,Android中调用系统管理器选择文件并返回绝对路径

    选择文件的时候,如果使用的是第三方软件,一般是直接返回绝对路径的Uri,如果是系统的,则会返回媒体库的xxxx,所以单纯一种方式选择文件,很可能拿到的绝对路径是错的或者是空的,所以需要做几种处理,这里 ...

  10. matlab图像读取原理,matlab中imread读入图像的原理

    imread的使用方法是: I=imread('C:\XXXX\XXXX.jpg'); I = imread('E:\2012\The standard image\Lena.bmp'); I1 = ...

最新文章

  1. android:themes.xml
  2. 阿里专家讲中台:技术中台-分布式架构在蚂蚁金服的实践
  3. 如何下载github项目中的某一部分
  4. Hive安装问题简述
  5. 从零开始学习jQuery (九) jQuery工具函数
  6. list中抽出某一个字段的值_使用LINQ获取List列表中的某个字段值
  7. 计算机网络 | IP协议相关技术与网络总结 :DNS、ICMP、DHCP、NAT/NAPT、通信流程
  8. 服务器日志显示意外关闭,服务器事件日志
  9. 序列化、模块 day21
  10. 【原创】开源Math.NET基础数学类库使用(04)C#解析Matrix Marke数据格式
  11. Linux查看和修改IP地址
  12. Bootstrap 模态框(Modal)
  13. php v9 用于静态页查询登陆状态以及用户信息的ajax接口,phpcms V9如何判断用户是否登录以及登陆后的标签写法问题 - 小众知识...
  14. springmvc和encache集成
  15. 汽车服务架构(SOA)开发设计
  16. html5 uc qq,(进阶版)手机浏览器用户体验报告:UC、QQ、360,到底哪个好?
  17. 计算机上的程序全是应用程序,手把手教你不是有效的 win32 应用程序怎么解决...
  18. 如何查看Steam的17位Id
  19. Profile多环境支持
  20. 【建议收藏】20个Python非常有用的单行代码

热门文章

  1. JavaWeb002-servlet基础
  2. iOS获取键盘的高度
  3. Hadoop学习笔记—18.Sqoop框架学习
  4. 解决ssh无操作自动断开[转载,已经验证]
  5. 关于编码的一切【转载】
  6. WCF 第十三章 可编程站点 所有都与URI相关
  7. MySQL—02—MySQL的操作
  8. Image Cloud Gallery
  9. Java十大bug之——包冲突
  10. Linux echo 显示内容颜色