网站首页 > 精选文章 / 正文
1-装饰器
1-1-基本概念
- 装饰器本质上是一个高阶函数,是一个可以接受函数作为参数并返回一个新函数的函数。
- 它的主要作用是在不改变原函数定义和调用方式的前提下,为原函数增加额外的功能。
- 它可以让你在不修改原函数代码的情况下,为函数添加额外的功能。通过使用装饰器,可以提高代码的复用性和可维护性
- 应用场景:常见的应用场景包括日志记录、权限验证、性能测试、缓存等。
1-2-语法
Python 使用 `@` 符号来应用装饰器。以下是一个简单的装饰器示例:
1-2-1-代码
# 定义一个装饰器函数
def my_decorator(func):
def wrapper():
print("wrapper()......begin......")
func()
print("wrapper()......end......")
return wrapper
# 使用装饰器
@my_decorator
def hello():
print("Hello!")
# 调用被装饰后的函数
hello()
1-2-2-输出结果
1-2-3-代码分析
- 在上述代码中,`my_decorator` 是一个装饰器函数,它接受一个函数 `func` 作为参数,并返回一个新的函数 `wrapper`。
- `wrapper` 函数在调用原函数 `func` 的前后分别添加了一些额外的操作。
- 使用 `@my_decorator` 语法糖,将 `hello` 函数传递给 `my_decorator` 进行装饰,这样调用 `hello` 函数时,实际上调用的是 `wrapper` 函数。
1-3-带参数的函数使用装饰器
如果原函数带有参数,装饰器中的 `wrapper` 函数也需要接受相应的参数,并将这些参数传递给原函数。示例如下:
1-3-1-代码
def my_decorator(func):
def wrapper(*args, **kwargs):
print("wrapper()......begin......")
result = func(*args, **kwargs)
print("wrapper()......end......")
return result
return wrapper
@my_decorator
def add(a, b):
return a + b
result = add(5, 10)
print(result)
1-3-2-输出结果
1-3-3-代码分析
在这个例子中,`wrapper` 函数使用 `*args` 和 `**kwargs` 来接受任意数量的位置参数和关键字参数,并将它们传递给原函数 `add`。
1-4-带参数的装饰器
装饰器本身也可以接受参数。这需要定义一个返回装饰器函数的高阶函数
1-4-1-代码
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def say_hi():
print("Hi!")
say_hi()
1-4-2-输出结果
1-4-3-代码分析
- 在这个例子中,`repeat` 是一个接受参数 `n` 的高阶函数,它返回一个装饰器函数 `decorator`。
- `decorator` 函数接受一个函数 `func` 作为参数,并返回一个新的函数 `wrapper`。
- `wrapper` 函数会重复调用原函数 `func` `n` 次。
1-5-应用场景
1-5-1-日志记录装饰器
日志记录在调试和监控程序运行状态时非常重要,使用装饰器可以方便地为多个函数添加日志记录功能。
代码
import logging
def log_decorator(func):
def wrapper(*args, **kwargs):
logging.basicConfig(level=logging.INFO)
logging.info(f"开始执行函数 {func.__name__},参数: args={args}, kwargs={kwargs}")
result = func(*args, **kwargs)
logging.info(f"函数 {func.__name__} 执行完毕,结果: {result}")
return result
return wrapper
@log_decorator
def add(a, b):
return a + b
result = add(3, 5)
输出结果
代码分析
- `log_decorator` 是一个装饰器函数,它接受一个函数 `func` 作为参数。
- `wrapper` 函数在调用原函数 `func` 前后分别记录了函数的执行信息,包括开始执行、传入的参数以及执行结果。
- `@log_decorator` 语法糖将 `add` 函数传递给 `log_decorator` 进行装饰,这样调用 `add` 函数时就会自动记录日志。
1-5-2-性能测试装饰器
在优化代码性能时,需要了解函数的执行时间,使用装饰器可以轻松实现函数执行时间的测量。
代码
import time
def performance_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"函数 {func.__name__} 执行时间: {end_time - start_time} 秒")
return result
return wrapper
@performance_decorator
def slow_function():
time.sleep(2)
slow_function()
输出结果
代码分析
- `performance_decorator` 装饰器在调用原函数前后分别记录了时间,通过计算时间差得到函数的执行时间,并将其打印输出。
- 对 `slow_function` 函数应用该装饰器后,每次调用该函数都会显示其执行时间。
1-5-3-权限验证装饰器
在 Web 应用或其他需要权限控制的场景中,可使用装饰器来验证用户是否具有执行某个函数的权限。
代码
def permission_required(permission):
def decorator(func):
def wrapper(*args, **kwargs):
# 这里简单模拟权限验证,实际应用中需要根据具体情况实现
if permission == "admin":
print("权限验证通过")
return func(*args, **kwargs)
else:
print("权限不足,无法执行该操作")
return wrapper
return decorator
@permission_required("admin")
def sensitive_operation():
print("执行敏感操作")
sensitive_operation()
@permission_required("operator")
def sensitive_operation():
print("执行敏感操作")
sensitive_operation()
输出结果
代码分析
- `permission_required` 是一个带参数的装饰器,它接受一个权限参数 `permission`,并返回一个装饰器函数 `decorator`。
- `decorator` 函数接受原函数 `func` 作为参数,`wrapper` 函数在调用原函数之前进行权限验证。如果权限验证通过,则调用原函数;否则,输出权限不足的提示信息。
- `@permission_required("admin")` 为 `sensitive_operation` 函数添加了权限验证功能,只有具有 “admin” 权限的用户才能执行该函数。
1-5-4-缓存装饰器
在处理一些计算量较大且结果不经常变化的函数时,使用缓存装饰器可以避免重复计算,提高程序的运行效率。
代码
def cache_decorator(func):
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@cache_decorator
def factorial(n):
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)
print(factorial(5))
print(factorial(5)) # 第二次调用时直接从缓存中获取结果
输出结果
代码分析
- `cache_decorator` 装饰器使用一个字典 `cache` 来存储函数的输入参数和对应的计算结果。
- `wrapper` 函数在调用原函数之前,先检查输入参数是否已经存在于缓存中。如果存在,则直接返回缓存中的结果;否则,调用原函数进行计算,并将结果存入缓存。
- 对 `factorial` 函数应用该装饰器后,当多次调用相同参数的 `factorial` 函数时,只有第一次会进行实际计算,后续调用会直接从缓存中获取结果。
Tags:wrapper or
猜你喜欢
- 2025-04-05 高并发下Spring Cache缓存穿透?我用Caffeine+Redis破局
- 2025-04-05 还搞不清Spring 与 Spring MVC 容器之间的关系?
- 2025-04-05 Java中9种常见的CMS GC问题分析与解决(一)
- 2025-04-05 ROS2 机械臂 MoveIt 开发必看!用 MTC 实现抓取任务规划(附解析)
- 2025-04-05 Linux高性能服务器设计(linux高性能服务端编程)
- 2025-04-05 Docker系列 搭建自动备份服务duplicati
- 2025-04-05 打通 JAVA 与内核系列之 一 ReentrantLock 锁的实现原理
- 2025-04-05 MyBatis-Flex一个优雅的 MyBatis增强框架
- 2025-04-05 抖音品质建设 - iOS启动优化《实战篇》
- 2025-04-05 GitHub 7.5k star量,各种视觉Transformer的PyTorch合集整理好了