装饰器(1)
一、定义
装饰器就是闭包函数的一种应用场景
装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
二、作用
开放封闭原则:对修改封闭,对扩展开放
三、装饰器的使用

import time def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper @timmer def foo(): time.sleep(3) print('from foo') foo()

def auth(driver='file'): def auth2(func): def wrapper(*args,**kwargs): name=input("user: ") pwd=input("pwd: ") if driver == 'file': if name == 'egon' and pwd == '123': print('login successful') res=func(*args,**kwargs) return res elif driver == 'ldap': print('ldap') return wrapper return auth2 @auth(driver='file') def foo(name): print(name) foo('egon') 有参装饰器

def auth(x,engine = "file"): def outter(func): def wrapper(*args, **kwargs): x name = input("username>: ").strip() pwd = input("password>: ").strip() if engine == "file": if name == "egon" and pwd == "123": print('login successful'.center(50,'=')) res = func(*args, **kwargs) return res else: print('username or password error') elif engine == "mysql": print("基于mysql的认证") elif engine == "ldap": print("基于ldap的认证") else: print('engine不存在') return wrapper return outter @auth(11,"file") # @outter函数的内存地址 # index=outter函数的内存地址(index函数的内存地址) def index(): print('from index') @auth(11,"mysql") def home(name): print('welcome %s to home page' %name) # index=auth(index,"file") # home=auth(index,"ldap") index() home("egon") # 模板 def outter2(x): def outter1(func): def wrapper(*args, **kwargs): res = func(*args, **kwargs) return res return wrapper return outter1 @outter2(x=1) def index(): pass
四、装饰器语法
1 2 3 4 5 6 7 8 | #被装饰函数的正上方,单独一行 @deco1 @deco2 @deco3 def foo(): pass foo = deco1(deco2(deco3(foo))) |
五、装饰器补充
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from functools import wraps def deco(func): @wraps (func) #加在最内层函数正上方 def wrapper( * args, * * kwargs): return func( * args, * * kwargs) return wrapper @deco def index(): '''哈哈哈哈''' print ( 'from index' ) print (index.__doc__) |
六、叠加多个装饰器
1 2 3 | # 叠加多个装饰器 # 1. 加载顺序(outter函数的调用顺序):自下而上 # 2. 执行顺序(wrapper函数的执行顺序):自上而下 |

def outter1(func1): #func1=wrapper2的内存地址 print('加载了outter1') def wrapper1(*args,**kwargs): print('执行了wrapper1') res1=func1(*args,**kwargs) return res1 return wrapper1 def outter2(func2): #func2=wrapper3的内存地址 print('加载了outter2') def wrapper2(*args,**kwargs): print('执行了wrapper2') res2=func2(*args,**kwargs) return res2 return wrapper2 def outter3(func3): # func3=最原始的那个index的内存地址 print('加载了outter3') def wrapper3(*args,**kwargs): print('执行了wrapper3') res3=func3(*args,**kwargs) return res3 return wrapper3 @outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址 @outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址 @outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址 def index(): print('from index') print('======================================================') index() 示范代码

# def deco1(func1): # func1 = wrapper2的内存地址 # def wrapper1(*args, **kwargs): # print('====>wrapper1') # res1 = func1(*args, **kwargs) # return res1 # return wrapper1 # # def deco2(func2): # func2 = wrapper3的内存地址 # def wrapper2(*args, **kwargs): # print('====>wrapper2') # res2 = func2(*args, **kwargs) # return res2 # return wrapper2 # # def deco3(func3): # func3 = index函数的内存地址 # def wrapper3(*args, **kwargs): # print('====>wrapper3') # res3 = func3(*args, **kwargs) # return res3 # return wrapper3 # # # 加载/得到wrapper函数的顺序是自下而上的 # # 我们运行wrapper函数的顺序是: # # # index=wrapper1的内存地址 # @deco1 # deco1(wrapper2的内存地址) => wrapper1的内存地址 # @deco2 # deco2(wrapper3的内存地址) => wrapper2的内存地址 # @deco3 # deco3(index函数的内存地址) => wrapper3的内存地址 # def index(): # print('from index') # # # print(index) # res=index() # """ # ====>wrapper1 # ====>wrapper2 # ====>wrapper3 # from index # """ import time def timmer(func): def wrapper(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print("run time is : %s" %(stop - start)) return res return wrapper # 千万不要加括号 def auth(x,engine = "file"): def outter(func): def wrapper(*args, **kwargs): x name = input("username>: ").strip() pwd = input("password>: ").strip() if engine == "file": if name == "egon" and pwd == "123": print('login successful'.center(50,'=')) res = func(*args, **kwargs) return res else: print('username or password error') elif engine == "mysql": print("基于mysql的认证") elif engine == "ldap": print("基于ldap的认证") else: print('engine不存在') return wrapper return outter @auth(111,"file") @timmer def index(): print("index=====>") time.sleep(3) index()
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 2025成都.NET开发者Connect圆满结束
· 后端思维之高并发处理方案
· 千万级大表的优化技巧
· 在 VS Code 中,一键安装 MCP Server!
· 10年+ .NET Coder 心语 ── 继承的思维:从思维模式到架构设计的深度解析