【python技巧009】画图直观展示装饰器的本质, 来N层装饰器都不怕了!

装饰器怎么用
函数理解成:“带窟窿的纸盒子盒子” 装饰器加工过程 涂鸦方式 直观展示 直观理解装饰器 会写装饰器 展示一些种装饰器实例: 添加日志、修改参数位置 保险处理、统计函数执行次数 延迟执行函数、多次执行函数 多层装饰器 多层装饰的顺序问题 带参数的装饰器 类装饰器
实现得一些现成的装饰器
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')