装饰器怎么用
https://www.bilibili.com/video/BV1sT4y1679u?spm_id_from=333.999.0.0
函数理解成:“带窟窿的纸盒子盒子”
装饰器加工过程 涂鸦方式 直观展示
直观理解装饰器
会写装饰器
展示一些种装饰器实例:
添加日志、修改参数位置
保险处理、统计函数执行次数
延迟执行函数、多次执行函数
多层装饰器
多层装饰的顺序问题
带参数的装饰器
类装饰器
直观理解
函数就是不同形状的盒子
有一个小机器人,你给小机器人一个盒子,这个小机器人会加工这个盒子,怎么加工的呢?
调皮的小机器人新造了一个和你这个盒子的形状(左右窟窿数量一样)的新盒子,然后把你给他的盒子放到新盒子里,(可能在这中间还会多塞进去一些新东西)装好之后再把这个新盒子给你,并说:“加工好了啦~”
翻译:
你有一个装饰器,你给装饰器一个函数,这个装饰器会加工这个函数,怎么加工的呢?
调皮的装饰器新造了一个和你这个函数的形状(参数数量和返回值类型一样)的新空函数,然后把你给他的函数放到新函数里,(可能在这中间还会加一些新功能)装好之后再把这个新函数给你,并说:“装饰好了啦~”
实现得一些现成的装饰器
def logger(oldFunc):
"""夹层装饰器,给函数调用前后加两个打印突出显示"""
def newFunc():
print("~~~~~~~~~~~")
oldFunc()
print("~~~~~~~~~~~")
...
return newFunc
def logger2(oldFunc):
"""夹层装饰器,只给头顶增加一个打印"""
def newFunc():
print("+++++++++++")
oldFunc()
...
return newFunc
def runDouble(oldFunc):
"""给一个函数装饰,装饰后这个函数就能运行两次了"""
def newFunc():
oldFunc()
oldFunc()
return newFunc
def counter(oldFunc):
"""记录一个函数打印了多少次"""
count = 0
def newFunc():
nonlocal count
count += 1
oldFunc()
print(f"这个函数{oldFunc.__name__}运行了{count}次")
...
return newFunc
def shield(oldFunc):
"""防护盾装饰器,让一个函数在运行中不会发生错误导致程序终止"""
def newFunc():
try:
oldFunc()
except Exception as e:
print(f"函数{oldFunc.__name__}出错了", oldFunc, e)
return newFunc()
from functools import lru_cache
@lru_cache(None)
def func():
print("hello")
@lru_cache()
def func2():
...
class Check(object):
"""类装饰器"""
def __init__(self, fn):
"""
传入的是被装饰的原的函数
"""
self.__fn = fn
def __call__(self, *args, **kwargs): # 实现__call__方法,表示对象是一个可调用对象,可以像调用函数一样进行调用
print("登录") # 在这之前可以写登录代码
self.__fn()
带参数的装饰器
写法是套了三层def,中间那层def是原来的装饰器的那个(小机器人)。
import time
"""
带参数的选择器
timer() 加小括号调用结束之后,本身会变成一个不带参数的装饰器(小机器人)
然后这个装饰器再对函数进行装饰
"""
def timer(time_type):
print(time_type)
if time_type == "min":
def robot(func):
print("func的名字是:", func.__name__)
def inner(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
end = time.time()
res = end - start
print('时间结果是:', res)
return inner
else:
def robot(func):
print("func的名字是:", func.__name__)
def inner(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
end = time.time()
res = end - start
print('时间结果是:', res)
return inner
return robot
@timer('min')
def foo(a, b, c):
print('in foo', a, b, c)
foo('a', 'bb', 'ccc')