一、装饰器
1.作用:不改变函数或类的源代码基础上,为其添加额外功能
2.原则:开闭原则,对扩展开放,对修改关闭
3.本质:闭包+高阶函数,接收callback(可调用)对象传入
二、函数实现装饰器
1.无参(两层装饰器)
import time
import functools
def cost_time(func):
@functools.wraps(func) #保留原函数名字、文档注释
def inner(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"执行{func.__name__}花费{end‑start}s")
return res #必须返回原函数结果
return inner
@cost_time
def add(a,b):
time.sleep(1)
return abs(a)+abs(b)

2.带参(三层函数装饰器)
装饰器需要传入自定义参数,多一层接收参数
import functools
def authorized(username,password):
#第一层:接收装饰器参数
def certify(func):
#第二层:接收被装饰函数
@functools.wraps(func)
def inner(*args,**kwargs):
#第三层:真正业务逻辑
if username=="root" and password=="123456":
return func(*args,**kwargs)
else:
print("登录失败")
return inner
return certify
@authorized(username="root",password="123456")
def add(a,b):
return abs(a)+abs(b)
#等价 add = authorized("root","123456")(add)
三、类实现装饰器
核心魔术方法:
init:实例化时执行
call:对象加括号obj()自动触发
1.无参类装饰器 @A
import time
class A:
def __init__(self,func):
self.func = func #接收被装饰函数
def __call__(self,*args,**kwargs):
start = time.time()
res = self.func(*args,**kwargs)
end = time.time()
print(f"执行{self.func.__name__}花费{end‑start}s")
return res
@A
def add(a,b):
time.sleep(1)
return abs(a)+abs(b)
#等价 add = A(add)
2.带参类装饰器 @A(username="",password="")
import functools
class A:
def __init__(self, username, password):
# __init__只接收装饰器参数,拿不到func
self.username = username
self.password = password
def __call__(self,func):
# __call__接收被装饰函数func
@functools.wraps(func)
def inner(*args,**kwargs):
if self.username=="root" and self.password=="123456":
return func(*args,**kwargs)
else:
print("登录失败")
return inner
@A(username="root", password="123456")
def add(a,b):
return abs(a)+abs(b)
#等价 add = A("root","123456")(add)
| 类型 | 写法 | 关键 |
|---|---|---|
| 无参函数装饰器 | 2层函数 | 外层接受func,return inner |
| 带参函数装饰器 | 3层函数 | 第1层接受装饰器函数 |
| 无参类装饰器 | @A | init(self,func);call(*args,**kwargs) |
| 带参类装饰器 | @A(参数) | __init__接受装饰器参数; call(self,func)接受被装饰函数 |