1.装饰器介绍
在Python中,装饰器通常是一种函数,它可以接受一个函数作为参数,并返回一个新的函数。装饰器通常用于修改函数或类的行为,而不需要修改函数或类的源代码。
装饰器是一种基于闭包(closure)思想的Python语言特性,也是python语言中的语法糖。
(闭包是指在函数内部定义的函数,它可以访问外部函数的变量,并且可以在外部函数返回后继续访问这些变量。)
2.使用场景
装饰器可以用于很多场景,例如:
-
日志记录。可以使用装饰器记录函数的执行时间、输入参数、输出结果等信息,便于调试和分析。
-
缓存数据。可以使用装饰器缓存函数的计算结果,避免重复计算,提高程序的执行效率。
-
权限控制。可以使用装饰器限制某些函数只能被特定的用户或者角色访问,保证程序的安全性。
-
事务管理。可以使用装饰器在函数执行前开启一个事务,在函数执行后提交或者回滚事务,保证数据的一致性。
3.例子
简单例子一
下面这个装饰器用于打印函数的执行时间:
import time
def log_time(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time} seconds to execute.")
print(f"Input arguments: args={args}, kwargs={kwargs}")
return result
return wrapper
@log_time
def my_function(a, b):
time.sleep(2)
return a + b
print(my_function(1, 2))
# 输出结果
# Function my_function took 2.00010347366333 seconds to execute.
# Input arguments: args=(1, 2), kwargs={}
简单例子二
标记一个函数已经被弃用(该代码来自redis第三方库 utils模块)。
def warn_deprecated(name, reason="", version="", stacklevel=2):
import warnings
msg = f"Call to deprecated {name}."
if reason:
msg += f" ({reason})"
if version:
msg += f" -- Deprecated since version {version}."
warnings.warn(msg, category=DeprecationWarning, stacklevel=stacklevel)
def deprecated_function(reason="", version="", name=None):
"""
Decorator to mark a function as deprecated.
"""
# 使用@wraps(func)可以提高装饰器的可读性和可维护性,避免装饰器修改原函数的元信息。
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
warn_deprecated(name or func.__name__, reason, version, stacklevel=3)
return func(*args, **kwargs)
return wrapper
return decorator
@deprecated_function(reason="test_deprecated", version="0.1", name="add")
def add(a, b):
return a + b
add(22, 00)
输出结果:
如果装饰器不需要传递参数,那么通常只需要使用一层函数即可,如上例子一,如果装饰器需要传递参数,那么通常需要使用两层函数,如上例子二
类装饰器
类装饰器是一种用于装饰函数或类的装饰器,它是一个类,可以实现__call__()
方法,用于对被装饰的函数或类进行包装和修改。
class Timer:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
import time
start_time = time.time()
result = self.func(*args, **kwargs)
end_time = time.time()
print('Execution time: {}'.format(end_time - start_time))
return result
@Timer
def my_func():
import time
time.sleep(1)
my_func() # 输出 Execution time: 1.000000238418579