在很多时候,我们编写的程序总会有很多的重复代码。比如,我们想记录某个函数的执行时长,保存操作日志等,总是需要在代码中插入相应的代码段。那有没有一种方法,可以解决这部分代码段的频繁修改和插入操作呢?在Python中,为我们提供了一种工具——装饰器,它可以用来提高函数的功能,提高代码的复用度,减少代码冗余。本节就来讲讲装饰器。
<1> 装饰器语法
装饰器可以认为是一种函数的嵌套,由两层函数嵌套,必须先定义才能使用。首先,来分析下装饰器的语法结构。
如上所示,定义装饰器方框内:第一行定义了外层decorater(),其括号内制定变量function,目的是将被装饰函数传入内层函数。第二行定义了内层函数inner(),支持变量*args、**args(上节已经说明了意义,这里不缀述)。第三到第五行,是被装饰函数的执行和增强功能。第六行定义内层函数返回值为被装饰函数的返回值,注意该返回值定义错误,将导致被装饰函数无法正常返回指定结果。第七行定义了外层函数的返回值为内存函数名。
使用装饰器方框内:第一行使用@+装饰器函数名,表示接下来定义的函数将使用装饰器来增强函数功能。第二行及以后,是被装饰函数的编写部分。
到这里,应该已经明白了装饰器如何定义和使用了。一旦一个函数定义时使用了装饰器,那么后期调用该函数时,装饰器的作用将直接呈现出来。
<2> 时间装饰器
下面通过代码来演示一个时间装饰器的编写,如下:
# 定义时间装饰器
import time
deftimer(function):
defdecorater(*args,**kwargs):
t0 = time.time()
result = function(*args,**kwargs)
t1 = time.time()
print('Function name = {0}\nRuntime = {1:.2} seconds'.format(function.__name__,t1-t0))
return result
return decorater
# 使用装饰器
@timer
deftest1():
time.sleep(0.5)
>>> test1()
Function name = test1
Runtime = 0.5 seconds
上述代码,通过在内部函数增加了函数执行前后的时间获取,输出了对应函数的输出时长。通过@timer装饰器,我们可以判断被装饰函数的运行时长,从而判断代码效率。
<3> 日志装饰器
下面通过代码来演示一个日志装饰器的编写,如下:
import time
import os
def loger(function):
def decorater(*args,**kwargs):
t0 = time.time()
result = function(*args,**kwargs)
t1 = time.time()
logfile_name = '{0}_log.txt'.format(function.__name__)
if os.path.exists(logfile_name)!=True:
with open(logfile_name,mode='w') as lf:
print('Function name\tRuntime\tResult',file=lf)
print('{0}\t{1:.2}\t{2}'.format(function.__name__,t1-t0,result),file=lf)
else:
with open(logfile_name,mode='a') as lf:
print('{0}\t{1:.2}\t{2}'.format(function.__name__,t1-t0,result),file=lf)
return result
return decorater
@loger
def test2():
time.sleep(0.5)
return'success'
>>> test2()
打开的日志文档,如下:
上述代码,
通过在内部函数增加了函数执行前后的时间获取和执行后的日志记录。再利用@loger装饰器,我们可以记录被装饰函数的运行日志,从而方便被装饰函数的问题排查。
<4> 总结
本节对装饰器的语法结构进行了讲解,并实例演示了时间装饰器和日志装饰器的编写。在实际使用中,我们可以善用装饰器,从而提高代码效率,降低代码冗余度。
-----------------------------
延伸阅读:
Python入门:第 1 章 Python 介绍
Python入门:第 2 章 环境搭建与第一个程序
Python入门:第 3 章 基本语法
Python入门:第 4 章 数据结构
Python入门:第 5 章 函数
Python入门:第 6 章 类
Python入门:第 7 章 文件读写
Python入门:第 8 章 Python多进程
Python入门:第 9 章 进程间通信
Python入门:第 10 章 消息队列
自动化办公1——初识Pandas
自动化办公2——Pandas数据结构
自动化办公3——Pandas数据操作1
自动化办公3——Pandas数据操作2
自动化办公4——Pandas数据组合、连接与重构
自动化办公5——Pandas数据透视表
自动化办公6——Pandas数据分组1
自动化办公6——Pandas数据分组2
自动化办公7——Pandas画图
数据可视化——matplotlib基础
数据可视化——matplotlib进阶
数据可视化——seaborn初识
数据可视化——seaborn绘制关系图
数据可视化——seaborn绘制分布图
科学计算1——Numpy初识
科学计算2——Numpy数组操作
科学计算3——Numpy数组变形
科学计算4——Numpy的索引与切片
科学计算5——Numpy的基本计算
科学计算6——Numpy的矩阵运算
使用 NumPy 求解线性方程组:一个完整案例
更多内容请查看微信公众号。
---------知识需要分享,需要传播---------
这里是Python知识驿站,致力于知识传播,让更多人了解Python、使用Python、爱上Python。如果你是一名程序员、业余开发者、IT从业者,或者任何一名对Python感兴趣的人,都可以加入Python知识驿站,让我们一同畅享在知识的海洋中。
---------关注我,获得更多知识---------