装饰器的概念以及优点
装饰器: 装饰器,装饰的对象是函数或者方法。各种装饰器的作用都是一样的:改变被装饰函数或者方法的功能,性质。
装饰器本质上是一个Python函数(其实就是闭包),它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。装饰器用于有以下场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。
装饰器特点:
- 不改变被装饰的函数的源代码的情况下添加函数的功能
- 不改变被装饰的函数的调用方式
装饰器优点:
- 程序可读性高
- 代码复用性高
- 你的编程思路更加宽广
为啥使用装饰器
我们有一个函数my_fun(mesage),如下:
def my_fun(message):
print("Hello {message}")
如果我们要在这个my_fun(message)中,print代码前增加一个输出welcome的命令,我们可以通过增加print(“welcome”)来进行操作,如下:
def my_fun(message):
print("welcome")
print("Hello {message}")
但是如果我们需要增加print(“welcome”)的函数特别多,且print(“welcome”)又多次变更其他提示信息,那我们还要一个一个的给函数增加或者修改吗??那样是不是特别耗费时间,且修改的地方较多,装饰器可以解决这个问题。
不带参数的装饰器
装饰器的使用
调用装饰器的方法有两种,第一种最常用,如下:
#不带参数的装饰器
#自定义装饰器
def welcome(fn):
def wrapper(*args, **kargs):
print("welcome")
result = fn(*args, **kargs)
return result
return wrapper
@welcome
def my_fun(message):
print(f"Hello {message}")
# 装饰器的调用有两种方法:
# 第一种,第一步-先在需要调用的函数前加@welcome
# 第二步:然后调用需要调用的函数即可
my_fun('zhangsan')
print(my_fun) # <function welcome.<locals>.wrapper at 0x000001F1D2215488>
第二种,如下:
#不带参数的装饰器
#自定义装饰器
def welcome(fn):
def wrapper(*args, **kargs):
print("welcome")
result = fn(*args, **kargs)
return result
return wrapper
def my_fun(message):
print(f"Hello {message}")
f1 = welcome(my_fun) # 获得内部函数wrapper函数
res = f1("jack") # 调用wrapper函数
装饰器的优化
my_fun()–调用的是my_fun函数,但是在打印函数的时候,确显示为wrapper函数,这个怎么处理呢?使用wraps装饰器即可解决,如下:
from functools import wraps
#自定义装饰器
def welcome(fn):
@wraps(fn)
def wrapper(*args, **kargs):
print("welcome")
result = fn(*args, **kargs)
return result
return wrapper
@welcome
def my_fun(message):
print(f"Hello {message}")
# 装饰器的调用有两种方法:
# 第一种,第一步-先在需要调用的函数前加@welcome
# 第二步:然后调用需要调用的函数即可
my_fun('zhangsan')
print(my_fun) # <function my_fun at 0x00000209CA435488>
方法如下:
第一步:先导入wraps方法-from functools import wraps
第二步:在自定义装饰器函数中增加@wraps(fn),这个fn的参数是不需要要写的。
带参数的装饰器
# 带参数的装饰器
from functools import wraps
def welcome(name):
def decorator(fn):
@wraps(fn)
def wrapper(*args, **kargs):
print(f"welcome {name}")
result = fn(*args, **kargs)
return result
return wrapper
return decorator
@welcome('Tom') #装饰器会先执行welcom("Tom")返回一个装饰器函数,然后在执行@
def my_fun(message):
print(f"hello {message}")
my_fun("JACK")
例子
使用装饰器,分别计算1+…+100和1+…1000的花费时间,请用装饰器实现
from functools import wraps
import time
def getTimer(fn):
@wraps(fn)
def wrapper(*args, **kargs):
start_time = time.time()
result = fn(*args, **kargs)
end_time = time.time()
print(f"共花费{end_time-start_time}秒")
return result
return wrapper
@getTimer
def add(num):
total = 0
for i in range(num):
total += i
return total
print(add(101))
print(add(10000001))
# 共花费0.0秒
# 5050
# 共花费2.4837872982025146秒
# 50000005000000