当前位置: 首页 > news >正文

装饰器

装饰器

# 1.什么是装饰器
# ● 概括地讲,装饰器的作用就是在不修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能。
# ● 装饰器经常用于有切面需求的场景:
#   插入日志、性能测试、事务处理、缓存、权限校验等应用场景
#   装饰器是解决这类问题的绝佳设计
#   有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。# 2.装饰器的用途
# ● 软件的设计应该遵循开放封闭原则,即对扩展是开放的,而对修改是封闭的。
#   对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
#   对修改封闭,意味着对象一旦设计完成,就可以独立完成其工作,而不要对其进行修改。
# ● 软件包含的所有功能的源代码以及调用方式,都应该避免修改,否则一旦改错,则极有可能产生连锁反应,最终导致程序崩溃
#   而对于上线后的软件,新需求或者变化又层出不穷,我们必须为程序提供扩展的可能性,这就用到了装饰器。
# 3.装饰器的分类
# ● 函数装饰器分为:无参装饰器和有参装饰两种
# ● 二者的实现原理一样,都是‘函数嵌套+闭包+函数对象’的组合使用的产物。

无参装饰器

引入

import timestart_time = time.time()
time.sleep(2)
end_time = time.time()print(end_time - start_time) 
  • 将计时功能做成一个函数,每次使用的时候进行调用即可
def index():print('index 运行')time.sleep(2)return 'index 运行结束'def home():print('func 运行')time.sleep(2)return 'func 运行结束'def timer(func):print(func) start_time = time.time()res = func() # 获取到传入进来的函数的内存地址 ---> 执行函数end_time = time.time()print(f"总耗时 :>>>> {end_time - start_time}s")return res
res = timer(func=index)
print(res)
res = timer(func=home)
print(res)
  • 计时功能优化,不改变原函数的调用方式
def home():print('func 运行')time.sleep(2)return 'func 运行结束'
def index():print('index 运行')time.sleep(2)return 'index 运行结束'def timer(func):# print(func)  def inner():start_time = time.time()res = func()  # 获取到传入进来的函数的内存地址 ---> 执行函数end_time = time.time()print(f"总耗时 :>>>> {end_time - start_time}s")return resreturn inner
print(index) 
index = timer(func=index)
print(index)
print(index())home = timer(func=home)
print(home)
print(home())
  • 小结
def index():print(f"index starting----")time.sleep(2)return 'index 运行结束'# 给原本的函数 index 加上一个 计时功能并且不要改变原来的调用方式
# index()
def timer(func):# func ---> index 真正的函数内存地址def inner():result = func()# 原本的 index 函数 可能会有返回值return resultreturn innerindex = timer(func=index)  # index 就是 timer 内的 inner 的内存地址
result = index()  # index() ---> timer 内的 inner 执行 ---> func() --->  index 真正的函数内存地址 ---> index()
# result 是你真正的index 函数执行后返回的返回值

有参装饰器

login_dict = {"username": "dream","password": "521"
}def withdraw(username, money):print(f"当前用户{username}正在提现{money}元")def transform(username, to_username, money):print(f"当前用户{username} 给 {to_username} 转账了 {money}元")# withdraw(username="dream", money="521")
def login_auth(func):def inner(username, money):if login_dict.get("username"):return func(username, money)  # withdraw(参数)else:return False, f'当前请先登陆!'return innerwithdraw = login_auth(withdraw)
# withdraw(username, money)
res = withdraw(username="dream",money=999)  # withdraw --> login_auth 内 的 inner ---> inner() ---> func() ---> withdraw()
print(res)
  • 有参装饰器模板
def outer(func):def inner(*args, **kwargs):# 第一部分 在正式进入func 之前进行校验# 第二部分 正式执行 原本的函数result = func(*args, **kwargs)# 第三部分 对返回的结果进行处理然后返回return resultreturn inner
  • 有参装饰器
def withdraw(username, money):return f"当前 {username} 取款 {money} 元!"def transform(username, to_username, money):return f'当前 {username} 给 {to_username}转账 {money} 元!'def login_auth(func):def inner(*args, **kwargs):if not login_dict.get("username"):return "当前未登录请先登陆!"return func(*args, **kwargs)return inner
# login_auth(withdraw) 返回值是 login_auth 里面的 inner 函数的内存地址
# 给 login_auth 里面的 inner 函数的内存地址 重新赋值 withdraw
withdraw = login_auth(withdraw)
# withdraw() ---> login_auth 里面的 inner() ---> inner 里面的func() ---> withdraw() ---> 原本真正的函数()
withdraw("dream", 1000)

语法糖

  • Python开发者为了更加方便的给当前函数加上指定的装饰器 于是就有了一种新语法
  • 语法糖 : 语法糖就是一种便捷的语法 本质还是原来的语法
login_dict = {"username": "dream","password": "521"
}def login_auth(func):def inner(*args, **kwargs):if not login_dict.get("username"):return "当前未登录请先登陆!"return func(*args, **kwargs)return inner@login_auth  # 相当于 withdraw = login_auth(withdraw)
def withdraw(username, money):return f"当前 {username} 取款 {money} 元!"print(withdraw("dream",521))@login_auth
def transform(username, to_username, money):return f'当前 {username} 给 {to_username}转账 {money} 元!'print(transform("dream","hope",521))
  • 多层语法糖
login_dict = {"username": "dream","role": "admin"
}def login_decorator(func):# func ---> withdraw 函数的内存地址def inner(*args, **kwargs):print("login_decorator")if not login_dict.get("username"):return "当前未登录请先登陆!"return func(*args, **kwargs)return innerdef permission_decorator(func):# func ---> login_decorator 的 inner 函数地址def inner(*args, **kwargs):print("permission_decorator")if login_dict.get("role") != "admin":return "当前没有权限访问当前功能!"return func(*args, **kwargs)return inner# 多层语法糖的包装顺序是从下向上包装
# 执行顺序是从上向下执行@login_decorator  # withdraw = login_decorator(permission_decorator 里面的 inner) =  login_decorator 里面的 inner 函数地址
@permission_decorator  # withdraw = permission_decorator(withdraw真正的) = permission_decorator 里面的 inner
def withdraw(username, money):return f"当前 {username} 取款 {money} 元!"# 这里的 withdraw 函数的内存地址是 login_decorator 里面的 inner 函数地址
res = withdraw("Dream", "9999")
print(res)

有参语法糖

  • 有参语法糖前身
login_dict = {"username": "dream","role": "admin"
}def decorator(tag):# print(tag)  if tag == "login":def login_decorator(func):# func ---> withdraw 函数的内存地址def inner(*args, **kwargs):print("login_decorator")if not login_dict.get("username"):return "当前未登录请先登陆!"return func(*args, **kwargs)return innerreturn login_decoratorelif tag == "permission":def permission_decorator(func):# func ---> login_decorator 的 inner 函数地址def inner(*args, **kwargs):print("permission_decorator")if login_dict.get("role") != "admin":return "当前没有权限访问当前功能!"return func(*args, **kwargs)return innerreturn permission_decorator# withdraw = login_decorator(withdraw) 的返回值  = login_decorator 的 inner 函数地址
login_auth = decorator(tag="login")
permission = decorator(tag="permission")withdraw = permission(withdraw)  # withdraw = permission_decorator(withdraw)
withdraw = login_auth(withdraw)  # withdraw = login_decorator(withdraw)
print(withdraw("Dream", 999))
  • 有参语法糖真身
login_dict = {"username": "dream","role": "admin"
}def decorator(tag):# print(tag)  if tag == "login":def login_decorator(func):# func ---> withdraw 函数的内存地址def inner(*args, **kwargs):print("login_decorator")if not login_dict.get("username"):return "当前未登录请先登陆!"return func(*args, **kwargs)return innerreturn login_decoratorelif tag == "permission":def permission_decorator(func):# func ---> login_decorator 的 inner 函数地址def inner(*args, **kwargs):print("permission_decorator")if login_dict.get("role") != "admin":return "当前没有权限访问当前功能!"return func(*args, **kwargs)return innerreturn permission_decorator@decorator(tag='login')  # @login_decorator
@decorator(tag='permission')  # @permission_decorator
def withdraw(username, money):return f"当前 {username} 取款 {money} 元!"print(withdraw("Dream", 999))
http://www.hskmm.com/?act=detail&tid=29673

相关文章:

  • 记录一下 WPF进程 SendMessage 发送窗口消息进行进程间通信,存在进程权限无法接受消息的问题
  • 正睿25noip十连测day5
  • kettle插件-dm数据库插件,解决kettle9.X版本无法连接数据库资源库问题
  • 2025年10月武汉防水公司TOP5权威推荐榜:专业施工与优质服务的行业
  • 2025开发区婚纱照公司最新权威推荐榜:创意拍摄与贴心服务的
  • 用户交互scanner方法学习及使用示例
  • 2025工业网线厂家最新权威推荐榜:稳定传输与耐用品质的首选
  • 完整教程:STM32H743-ARM例程11-PWM
  • 20231427田泽航实验一-4
  • 2025铝合金微弧氧化定制厂家权威推荐榜:品质卓越与技术创新
  • 20231427田泽航实验一-3
  • 信息安全设计/密码系统设计 实验1-1
  • 2025年10月拉伸器厂家最新权威推荐榜:高效稳定与卓越品质的行业首
  • 2025数粒机厂家最新权威推荐榜:精准高效与智能控制的行业首
  • Spring拦截器HandlerInterceptor与Filter方法执行顺序探究
  • 2025精加工车间恒温恒湿系统TOP5榜单:精准控温与高效节
  • 第四章作业
  • 2025数控滚齿机订制厂家权威推荐:高精度与高效能的首选品牌
  • 2025婚纱摄影工作室权威推荐榜:捕捉幸福瞬间的创意大师
  • 详细介绍:初学者小白复盘11之——指针(1)
  • 2025-10-12
  • hex、bin、axf文件的区别
  • 20232417 2025-2026-1 《网络与系统攻防技术》实验一实验报告
  • 2025黄金回收品牌TOP5权威榜单:值得信赖的高性价比厂家
  • [数据分析/BI] Microsoft Power BI 使用指南
  • 机器人技术在现实世界中的挑战与创新
  • Motorola和Inter的区别
  • ROS2之TF
  • 深入解析:2025年真实手机牧场CC攻击破防游戏盾?四维防御体系全面升级!
  • 代码源2025长训