Python中的装饰器一直是一个比较难理解的概念,我自己理解的就是用一个函数去修改另一个函数,主要是为另一个函数添加计时等功能,而且不用改变另一个函数,这样就大大减少了另一个函数的维护成本。
这个装饰器,英文名就是decorator,相关于把一个写好的程序添加一些新的功能,让这个程序变成多功能的。装饰器还可以传递参数,但如果要加参数就要多一层。
首先,我们看一个样例[1],有一个计算数字平方和的函数,我们添加一个装饰器elasped,来为它增加计算函数运行时间的功能。
一、不用@添加装饰器的写法
# 对目标函数进行elapsed装饰器函数的调用
# 返回一个装饰后的名字还是叫power_sum的函数
import time
def elapsed(target):
"统计函数执行的耗时:"
def decorated(*args,**kwargs):
start = time.time()
r = target(*args,**kwargs)
end = time.time()
print("函数执行耗时:", round(end - start, 2))
return r
return decorated
def power_sum(n):
"计算并返回1到n之间每个数的平方的和"
total = 0
for i in range(1,n+1):
total += i**2
return total
if __name__ == "__main__":
power_sum = elapsed(power_sum) # 相当于用装饰器函数elapsed调用了power_sum函数
print(power_sum(1000000))
二、使用@加装饰器的调用方法
# 对目标函数进行elapsed装饰器函数的调用
# 返回一个装饰后的名字还是叫power_sum的函数
import time
def elapsed(target):
"统计函数执行的耗时:"
def decorated(*args,**kwargs):
start = time.time()
r = target(*args,**kwargs)
end = time.time()
print("函数执行耗时:", round(end - start, 2))
return r
return decorated
@elapsed # 相当于用装饰器函数elapsed调用了power_sum函数相当于这行代码:power_sum = elapsed(power_sum)
def power_sum(n):
"计算并返回1到n之间每个数的平方的和"
total = 0
for i in range(1,n+1):
total += i**2
return total
if __name__ == "__main__":
print(power_sum(1000000))
调用结果:
三、为装饰器加上参数的方法
现在为装饰器加上参数,把函数执行耗时的时间加上可以控制保留小数位数的参数precision,结果如下:
# 对目标函数进行elapsed装饰器函数的调用
# 返回一个装饰后的名字还是叫power_sum的函数
import time
def elapsed_precision(precision):
def elapsed(target):
"统计函数执行的耗时:"
def decorated(*args,**kwargs):
start = time.time()
r = target(*args,**kwargs)
end = time.time()
print("函数执行耗时:", round(end - start, precision))
return r
return decorated
return elapsed
#不写就没有装饰器效果,写了相当于这一句:power_sum = elapsed(power_sum) 也就是power_sum被装饰后又重新命名为power_sum函数
@elapsed_precision(3)# 这里的3就是装饰器的参数。
def power_sum(n):
"计算并返回1到n之间每个数的平方的和"
total = 0
for i in range(1,n+1):
total += i**2
return total
if __name__ == "__main__":
print(power_sum(10000000))
由上述代码可见,我们加装饰器后,原来的函数没有变化,我们只是通过装饰器给power_sum函数添加计时功能,传递了一个保留小数位数的参数precision。
四、学后反思
1. 装饰器是python学习中一个比较难理解的概念,因为我们一直把函数的参数局限为字符、列表、元组、字典这些常用的数据结构,但是如果我们把函数看成一个对象,把一个函数作为另一函数(装饰器)的参数来调用就好理解了。
2. 装饰器可以使Python编写的代码更容易维护,同时也可以为函数增加更多的功能,是Python程序编写过程中一个重要的工具。
3. 在我学习Python的过程中,我一直对装饰器、多线程、异步这些概念模糊不清楚。虽然也有意去学习,但很多时候是一知半解,后来通过B站学习和个人的思考慢慢把这些概念理解弄通。