python函数装饰器参数统计调用时间和次数

1 python函数装饰器参数统计调用时间和次数

python在函数装饰器外层定义一个函数生成封闭作用域来保存装饰器入参,供装饰器使用。

1.1 装饰器统计调用时间和次数

描述

通过类的可调用实例装饰器来统计函数每次调用时间和总调用时间,以及调用次数。

(1) time.perf_counter()获取当前时间,单位秒;

(2) 调用函数func前和后的时间差,为func的执行时间usetime;

(3) 将每次的执行时间usetime累加,获得总时间alltime;

(4) 每调用一次func,calls计增一次获得总次数;

(5) 比较列表解析和map内置函数生成列表的调用时间;

(6) map在py2返回列表,在py3返回迭代器,需用list转为列表;

示例

>>> import time,sys
>>> class TimeCount:def __init__(self,func):self.func=funcself.alltime=0self.calls=0def __call__(self,*args,**kargs):begin=time.perf_counter()res=self.func(*args,**kargs)usetime=time.perf_counter()-beginself.alltime+=usetimeself.calls+=1callstr=' 调用 {0[0]} {0[1]} 次 'calltpl=self.func.__name__,self.callstimestr='{0[0]}:usetime={0[1]:.6f},alltime={0[2]:.6f}'timetpl=self.func.__name__,usetime,self.alltimeresstr='res[0]={0[0]},res[-1]={0[1]},len(res)={0[2]}'restpl=res[0],res[-1],len(res)print(callstr.format(calltpl).center(50,'-'))print(timestr.format(timetpl))print(resstr.format(restpl),'\n')>>> @TimeCount
def listcomp(N):return [x*2 for x in range(N)]>>> if sys.version_info[0]==2:@TimeCountdef mapcall(N):return map((lambda x:x*2),range(N))
else:@TimeCountdef mapcall(N):# py3的map返回迭代器需用list转换# 否则统计的时间与listcomp不一致return list(map((lambda x:x*2),range(N)))>>> xtpl=5,50000,500000,1000000
>>> tuple(map(listcomp,xtpl))
---------------- 调用 listcomp 1-----------------
listcomp:usetime=0.000005,alltime=0.000005
res[0]=0,res[-1]=8,len(res)=5 ---------------- 调用 listcomp 2-----------------
listcomp:usetime=0.002395,alltime=0.002400
res[0]=0,res[-1]=99998,len(res)=50000 ---------------- 调用 listcomp 3-----------------
listcomp:usetime=0.026660,alltime=0.029060
res[0]=0,res[-1]=999998,len(res)=500000 ---------------- 调用 listcomp 4-----------------
listcomp:usetime=0.053023,alltime=0.082084
res[0]=0,res[-1]=1999998,len(res)=1000000 (None, None, None, None)
>>> tuple(map(mapcall,xtpl))
----------------- 调用 mapcall 1-----------------
mapcall:usetime=0.000005,alltime=0.000005
res[0]=0,res[-1]=8,len(res)=5 ----------------- 调用 mapcall 2-----------------
mapcall:usetime=0.003963,alltime=0.003968
res[0]=0,res[-1]=99998,len(res)=50000 ----------------- 调用 mapcall 3-----------------
mapcall:usetime=0.041263,alltime=0.045231
res[0]=0,res[-1]=999998,len(res)=500000 ----------------- 调用 mapcall 4-----------------
mapcall:usetime=0.083637,alltime=0.128868
res[0]=0,res[-1]=1999998,len(res)=1000000 (None, None, None, None)
>>> '{:.6f}'.format(mapcall.alltime)
'0.128868'
>>> '{:.6f}'.format(listcomp.alltime)
'0.082084'
>>> '{:.6f}'.format(mapcall.alltime/listcomp.alltime)
'1.569957'

1.2 嵌套函数统计电影时间和次数

描述

通过嵌套函数来统计函数每次调用时间和总调用时间,以及调用次数。

(1) time.perf_counter()获取当前时间,单位秒;

(2) 调用函数func前和后的时间差,为func的执行时间usetime;

(3) 将每次的执行时间usetime累加,获得总时间alltime;

(4) 每调用一次func,calls计增一次获得总次数;

(5) 比较列表解析和map内置函数生成列表的调用时间;

(6) map在py2返回列表,在py3返回迭代器,需用list转为列表;

(7) 将alltime和calls赋值给func进行返回,供后续获取;

(8) 通过nonlocal修改嵌套作用域的变量alltime和calls;

示例

>>> import time,sys
>>> def timecount_func(func):alltime=0calls=0def tcf_wrapper(*pargs,**kargs):begin = time.perf_counter()res=func(*pargs,**kargs)usetime = time.perf_counter() - beginnonlocal alltimenonlocal callsalltime+=usetimecalls+=1timestr='{0[0]}:usetime={0[1]:.6f},alltime={0[2]:.6f}'timetpl=func.__name__,usetime,alltimecallstr=' 调用 {0[0]} {0[1]} 次 'calltpl=func.__name__,callsresstr='res[0]={0[0]},res[-1]={0[1]},len(res)={0[2]}'restpl=res[0],res[-1],len(res)print(callstr.format(calltpl).center(50,'-'))print(timestr.format(timetpl))print(resstr.format(restpl),'\n')func.alltime=alltimefunc.calls=callsreturn tcf_wrapper>>> def listcomp(N):return [x*2 for x in range(N)]>>> if sys.version_info[0]==2:def mapcall(N):return map((lambda x:x*2),range(N))
else:def mapcall(N):return list(map((lambda x:x*2),range(N)))>>> xtpl=5,50000,500000,1000000
>>> tuple(map(timecount_func(listcomp),xtpl))
---------------- 调用 listcomp 1-----------------
listcomp:usetime=0.000005,alltime=0.000005
res[0]=0,res[-1]=8,len(res)=5 ---------------- 调用 listcomp 2-----------------
listcomp:usetime=0.002478,alltime=0.002482
res[0]=0,res[-1]=99998,len(res)=50000 ---------------- 调用 listcomp 3-----------------
listcomp:usetime=0.031966,alltime=0.034448
res[0]=0,res[-1]=999998,len(res)=500000 ---------------- 调用 listcomp 4-----------------
listcomp:usetime=0.068800,alltime=0.103248
res[0]=0,res[-1]=1999998,len(res)=1000000 (None, None, None, None)
>>> tuple(map(timecount_func(mapcall),xtpl))
----------------- 调用 mapcall 1-----------------
mapcall:usetime=0.000006,alltime=0.000006
res[0]=0,res[-1]=8,len(res)=5 ----------------- 调用 mapcall 2-----------------
mapcall:usetime=0.004435,alltime=0.004441
res[0]=0,res[-1]=99998,len(res)=50000 ----------------- 调用 mapcall 3-----------------
mapcall:usetime=0.041257,alltime=0.045698
res[0]=0,res[-1]=999998,len(res)=500000 ----------------- 调用 mapcall 4-----------------
mapcall:usetime=0.082711,alltime=0.128409
res[0]=0,res[-1]=1999998,len(res)=1000000 (None, None, None, None)
>>> '{:.6f}'.format(mapcall.alltime)
'0.128409'
>>> '{:.6f}'.format(listcomp.alltime)
'0.103248'
>>> '{:.6f}'.format(mapcall.alltime/listcomp.alltime)
'1.243693'

1.3 函数装饰器参数

通过装饰器参数指定配置选项。在装饰的时候传入一个标签和一个跟踪控制标志。

提供一个输出标签,以及打开或关闭跟踪消息,

用法

def close_scope_func(label='',trace=True):def decorator(func):def onCall(*args):passfunc(*args)passreturn decorator@close_scope_func('梯阅线条')
def test_func(x):passtest_func('tyxt')

描述

装饰器参数需在外层添加一个函数生成一个封闭作用域用来保存参数,供装饰器使用。

(1) 在装饰器外层定义一个函数,并且指定装饰器需要的入参;

(2) 外层函数需返回一个可调用的装饰器,给到被装饰函数;

(3) 装饰函数时,传入对应入参即可;

示例

>>> import time,sys
>>> def timecount_ctr(label='',trace=True):class TimeCount:def __init__(self,func):self.func=funcself.alltime=0self.calls=0def __call__(self,*args,**kargs):begin=time.perf_counter()res=self.func(*args,**kargs)usetime=time.perf_counter()-beginself.alltime+=usetimeself.calls+=1if trace:callstr=' 调用 {0[0]} {0[1]} 次 'callval=self.func.__name__,self.callstimestr='{0[0]}:usetime={0[1]:.6f},alltime={0[2]:.6f}'timeval=self.func.__name__,usetime,self.alltimeresstr='res[0]={0[0]},res[-1]={0[1]},len(res)={0[2]}'resval=res[0],res[-1],len(res)print(label,callstr.format(callval).center(50,'-'))print(label,timestr.format(timeval))print(label,resstr.format(resval),'\n')return TimeCount>>> @timecount_ctr('[listcomp]==>')
def listcomp(N):return [x*2 for x in range(N)]>>> if sys.version_info[0]==2:@timecount_ctr('[mapcall]==>')def mapcall(N):return map((lambda x:x*2),range(N))
else:@timecount_ctr('[mapcall]==>')def mapcall(N):# py3的map返回迭代器需用list转换# 否则统计的时间与listcomp不一致return list(map((lambda x:x*2),range(N)))>>> xtpl=5,50000,500000,1000000
>>> tuple(map(listcomp,xtpl))
[listcomp]==> ---------------- 调用 listcomp 1-----------------
[listcomp]==> listcomp:usetime=0.000005,alltime=0.000005
[listcomp]==> res[0]=0,res[-1]=8,len(res)=5 [listcomp]==> ---------------- 调用 listcomp 2-----------------
[listcomp]==> listcomp:usetime=0.002641,alltime=0.002646
[listcomp]==> res[0]=0,res[-1]=99998,len(res)=50000 [listcomp]==> ---------------- 调用 listcomp 3-----------------
[listcomp]==> listcomp:usetime=0.027689,alltime=0.030335
[listcomp]==> res[0]=0,res[-1]=999998,len(res)=500000 [listcomp]==> ---------------- 调用 listcomp 4-----------------
[listcomp]==> listcomp:usetime=0.052438,alltime=0.082773
[listcomp]==> res[0]=0,res[-1]=1999998,len(res)=1000000 (None, None, None, None)
>>> tuple(map(mapcall,xtpl))
[mapcall]==> ----------------- 调用 mapcall 1-----------------
[mapcall]==> mapcall:usetime=0.000004,alltime=0.000004
[mapcall]==> res[0]=0,res[-1]=8,len(res)=5 [mapcall]==> ----------------- 调用 mapcall 2-----------------
[mapcall]==> mapcall:usetime=0.003975,alltime=0.003979
[mapcall]==> res[0]=0,res[-1]=99998,len(res)=50000 [mapcall]==> ----------------- 调用 mapcall 3-----------------
[mapcall]==> mapcall:usetime=0.040665,alltime=0.044644
[mapcall]==> res[0]=0,res[-1]=999998,len(res)=500000 [mapcall]==> ----------------- 调用 mapcall 4-----------------
[mapcall]==> mapcall:usetime=0.098298,alltime=0.142942
[mapcall]==> res[0]=0,res[-1]=1999998,len(res)=1000000 (None, None, None, None)
>>> '{:.6f}'.format(mapcall.alltime)
'0.142942'
>>> '{:.6f}'.format(listcomp.alltime)
'0.082773'
>>> '{:.6f}'.format(mapcall.alltime/listcomp.alltime)
'1.726914'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/615744.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#写windows服务,实现把检测软件崩溃工具写成服务 自动运行

一、打开Visual Studio,创建项目->Windows 服务(.NET Framework) 二、点击Service.cs 点击切换到代码视图 static Timer Timer; private Thread monitorThread; private static string logFilePath; private static Process winFormsProcess; public Service1(…

如何修复DLL错误或丢失的问题,这里提供几种方法

DLL错误是指DLL文件的任何错误,一种以.dll文件扩展名结尾的文件。 DLL错误可能出现在微软的任何操作系统中,包括Windows 10、Windows 8、Windows 7、Windows Vista和Windows XP。 DLL错误尤其麻烦,因为存在许多这样类型的文件,所…

obgs格式能通过Dasviewer导入到Revit吗?

答:Dasviewer可以支持las转换osgb,再通过osgb转换fbx或者obj。当然也可以通过重建的方式建模。 DasViewer是由大势智慧自主研发的免费的实景三维模型浏览器,采用多细节层次模型逐步自适应加载技术,让用户在极低的电脑配置下,也能流畅的加载较大规模实景三…

入门教程:使用 Postman 发送 post 请求

Postman 是一个实用的开发工具,它让发送各类 POST 请求成为了可能,包括文本、JSON、XML 以及文件等。开发者利用此工具不仅能够检验API的功能性,还能仿真客户端的请求行为,进而深入了解客户端如何与 API 进行互动。 HTTP 协议中的…

半小时实现GPT纯血鸿蒙版

仅需半小时,即可实现纯血鸿蒙版本的ChatGPT! 废话少说,先看效果图: 如上图所示,这个小Demo实现了AI智能问答。靠右加粗的文本是用户点击底部提交按钮后出现的;后面靠左对齐的普通文本是来自AI的回答内容。…

MySQL与Java JDBC数据类型对照

MySQL数据类型JAVA数据类型JDBC TYPEBIGINTLongBIGINTTINYINTByteTINYINTSMALLINTShortSMALLINTMEDIUMINTIntegerINTEGERINTEGERIntegerINTEGERINTIntegerINTEGERFLOATFloatREALDOUBLEDoubleDOUBLEDECIMALBigDecimalDECIMALNUMERICBigDecimalNUMERICCHARStringCHARVARCHARStrin…

(第48-59讲)STM32F4单片机,FreeRTOS【事件标志、任务通知、软件定时器、Tickless低功耗】【纯文字讲解】【原创】

文章目录 🔴🟡🟢其他文章链接,独家吐血整理1、纯文字(待补充) 🔴🟡🟢其他文章链接,独家吐血整理 【吐血总结】FreeRTOS难点、Systick中断-滴答定时器、PendS…

ES6语法详解+面试必备

ES6(ECMAScript 2015)是JavaScript的一个版本,它于2015年发布。ES6引入了很多新的语法和功能,使得JavaScript更加强大、灵活和易于使用。 一、块级作用域: ES6引入了let和const关键字,可以在块级作用域中…

IP定位技术:如何保护患者的隐私和医疗数据安全?

随着科技的飞速发展,互联网已经深入到我们生活的方方面面,医疗行业也不例外。然而,这也带来了网络安全问题。如何保护患者的隐私和医疗数据的安全,成为了医疗行业面临的重大挑战。IP定位技术的应用,为解决这一问题提供…

Unity中URP下抓屏的 开启 和 使用

文章目录 前言一、抓屏开启1、Unity下开启抓屏2、Shader中开启抓屏 二、抓屏使用1、设置为半透明渲染队列,关闭深度写入2、申明纹理和采样器3、在片元着色器使用请添加图片描述 三、测试代码 前言 我们在这篇文章中看一下,URP下怎么开启抓屏。 一、抓屏…

(代码模板)JAVA_返回类R

个人留存用,通用返回类R代码模板: import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data;import java.io.Serializable; import java.util.HashMap; import java.util.Map;/*** author &#…

《共建开源》系列:Airtest-Framework - UI自动化框架系统

Airtest- Framework 平台简介 Airtest- Framework 是 基于 unittest、Flask、Airtest 搭建的 开源的 UI 自动化框架系统 提供 HTTP API 接口,实现自动解析包名并自动执行 相应目录下的 Case。目前仅支持单台设备连接。多个任务会自动排队处理。 系统要求 Pytho…

【动态规划】【二分查找】C++算法 466 统计重复个数

作者推荐 【动态规划】458:可怜的小猪 涉及知识点 动态规划 二分查找 力扣:466 统计重复个数 定义 str [s, n] 表示 str 由 n 个字符串 s 连接构成。 例如,str [“abc”, 3] “abcabcabc” 。 如果可以从 s2 中删除某些字符使其变为 s1,则称字符串…

互信息法的原理详解

文章目录 互信息法(上)互信息是什么从信息增益角度理解互信息从变量分布一致角度理解互信息 卡方检验与离散变量的互信息法 互信息法(上) 尽管f_regression巧妙的构建了一个F统计量,并借此成功的借助假设检验来判断变…

跨境商城系统如何开发代购商城、国际物流、一件代发等功能?

跨境商城系统的开发涉及到多个方面,其中代购商城、国际物流和一件代发等功能是其中的重要组成部分。本文将详细介绍如何开发这些功能,以帮助跨境商城系统更好地满足市场需求。 一、代购商城的开发 代购商城是跨境商城系统中的重要功能之一,它…

互联网加竞赛 基于大数据的股票量化分析与股价预测系统

文章目录 0 前言1 课题背景2 实现效果3 设计原理QTChartsarma模型预测K-means聚类算法算法实现关键问题说明 4 部分核心代码5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于大数据的股票量化分析与股价预测系统 该项目较为新颖…

小程序基础学习(导航栏组件)

目标:把导航栏抽离成组件,

oracle 19c容器数据库data dump数据泵传输数据(2)---11g导19c

目录 1.在11gnon-cdb数据库中创建测试用户 2.在19cCDB容器数据库中新建pdb2 3.执行命令导出 4.执行命令导入 Exporting from a Non-CDB and Importing into a PDB 我們要記住一点:如果是全库导出导入的话,目标数据库没有的表空间我们要事先创建&#…

Java中输入和输出处理(四)序列化和反序列化

Java中输入和输出处理(四)序列化和反序列化的笔记 一、序列化 序列化是将对象的状态信息转换为可以存储或传输的形式的过程。在Java中,我们可以使用java.io.Serializable接口来实现对象的序列化。 示例: import java.io.*;clas…

提高iOS App开发效率的方法

引言 随着智能手机的普及,iOS App开发成为越来越受欢迎的技术领域之一。许多人选择开发iOS应用程序来满足市场需求,但是iOS App开发需要掌握一些关键技术和工具,以提高开发效率和质量。本文将介绍一些关键点,可以帮助你进行高效的…