python的函数代码块_Python功能点实现:函数级/代码块级计时器

本文介绍了如何在Python中优雅地实现代码计时,包括基于装饰器的函数级计时器和利用上下文管理器的代码块级计时器。通过装饰器,可以在不干扰原有代码逻辑的情况下为函数添加计时功能,而上下文管理器则允许对任意代码块进行计时,提供了更高的灵活性。此外,还展示了如何使用`contextlib.ContextDecorator`创建一个既可with语句使用也可作装饰器的计时器。
摘要由CSDN通过智能技术生成

关键词:计时器 | 装饰器 | 运行时上下文 | 代码块

工程中我们常常需要对某一个函数或者一块代码计时,从而监测系统关键位置的性能。计时方法是在代码块前后分别记录当前系统时间,然后两者相减得到代码块的耗时。最简单原始的实现类似:

from datetime import datetime

start = datetime.now()

# some code you want to measure

end = datetime.now()

print("Processing time for {} is: {} seconds".format('You Name It', elapse))

这种方式缺点明显:假如系统内有很多地方都需要计时,那么每个地方都需要插入这样的计时代码,首先是重复性工作很麻烦,其次这样会降低代码的可读性,干扰对业务逻辑的理解。本文将给出一些更好的实现,主要涉及的技术是装饰器(Decorator)和运行时上下文(runtime context)。

基于装饰器的函数级计时器

第一种计时器是比较常见的函数级计时器,通过装饰器完成,将原函数改装成拥有计时功能的新函数,使其可以完成运行原来函数和计时两件事。在使用时,只用在需要计时功能的函数代码前加上类似@timer的语法糖,这样每次调用原函数时,运行的将会是新函数。这样就大大减少了重复性劳动。

具体实现如下:

from datetime import datetime

def timer(func):

'''Function Level Timer via Decorator'''

def timed(*args, **kwargs):

start = datetime.now()

result = func(*args, **kwargs)

end = datetime.now()

elapse = (end - start).total_seconds()

print("Processing time for {} is: {} seconds".format(func.__name__, elapse))

return result

return timed

@timer

def test_1(a):

'''Function Level'''

a *= 2

return a

if __name__ == '__main__':

print(test_1(1))

基于上下文的代码块级计时器

装饰器实现的计时器可以为函数添加计时功能,可以满足大部分情况的需要,但是假如我们想要更灵活一些,对任意一段连续的代码块做计时,怎样做?使用原始的插计时代码的方法显然不是我们想要的;也可以将代码块重构成一个函数,再在上面加装饰器,然而这就显得不够优雅。因此我做出了下面的实现。

首先了解上下文管理的概念。大致是说Python中允许创建一种叫上下文管理器(Context Manager)的对象,它可以管理一个代码块执行时的上下文信息。具体的方法是创建一个类,并为其实现object.__enter__和object.__exit__方法,前者在进入代码块时自动执行,后者在完成代码块执行时自动执行。

在使用时,通过with和as关键字,将__enter__的返回值绑定到某一个变量名,这个返回值里可以储存代码块运行过程中得到的一些信息,在这里就是运行时间啦。具体的实现是创建一个计时器类Timer,在enter时记录代码块运行的开始时间,exit时记录完成时间、计算并储存耗时到Timer实例中。在使用时,将with Timer() as t加到要计时的代码块前面,t.elapse中将会储存代码块耗时,可以任意使用。

在这个基础上,我们还可以做出一个装饰器timer_来实现基于上下文的函数级计时器。

具体实现如下:

class Timer(object):

'''Code Block Level Timer via Context'''

def __enter__(self):

self.start = datetime.now()

return self

def __exit__(self, *args):

self.end = datetime.now()

self.elapse = (self.end - self.start).total_seconds()

def timer_(func):

'''Function Level Timer via Context & with Statement'''

def timed(*args, **kw):

with Timer() as t:

result = func(*args, **kw)

print("Processing time for {} is: {} seconds".format(func.__name__, t.elapse))

return result

return timed

def test_2(a):

'''Code Block Level'''

with Timer() as t:

a *= 2

print("Processing time for {} is: {} seconds".format('You Name It', t.elapse))

return a

@timer_

def test_3(a):

'''Function Level'''

a *= 2

return a

if __name__ == '__main__':

print(test_2(2))

print(test_3(3))

更灵活的实现

更优雅地,我们还可以使用contextlib自带的ContextDecorator,参考官方示例,做出既可以with又可以作为装饰器的计时器timer_elegant:

from datetime import datetime

from contextlib import ContextDecorator

class timer_elegant(ContextDecorator):

'''Elegant Timer via ContextDecorator'''

def __init__(self, name):

self.name = name

def __enter__(self):

self.start = datetime.now()

def __exit__(self, *args):

self.end = datetime.now()

self.elapse = (self.end - self.start).total_seconds()

print("Processing time for {} is: {} seconds".format(self.name, self.elapse))

@timer_elegant('test_4')

def test_4(a):

a *= 2

return a

def test_5(a):

a *= 2

return a

if __name__ == '__main__':

print(test_4(4))

with timer_elegant('test 5'):

result_5 = test_5(5)

print(result_5)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的高校科研信息管理系统实现了操作日志管理、字典管理、反馈管理、公告管理、科研成果管理、科研项目管理、通知管理、学术活动管理、学院部门管理、科研人员管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让高校科研信息管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值