日常使用 Python,装饰器使用的几率很多,那到底什么是装饰器呢?它又有哪些用处呢?
下面将逐一来说明
1. 什么是装饰器
装饰器(Decorator)是Python 中一种强大的语法特性,它允许在不修改原函数代码的情况下,动态地增强函数的功能。
实际上,装饰器本质上是一个高阶函数,它可以接收一个函数作为参数并返回一个新的函数。
def decorator(func):
def wrapper():
print("Before function execution")
func()
print("After function execution")
return wrapper
2. 装饰器的基本用法
使用 @ 符号来应用装饰器:
@decorator
def say_hello():
print("Hello!")
say_hello()
输出结果:
Before function execution
Hello!
After function execution
3. 装饰器的常见应用场景
3.1 日志记录
def log_execution(func):
def wrapper(*args, **kwargs):
print(f"Executing {func.__name__}...")
result = func(*args, **kwargs)
print(f"Finished executing {func.__name__}")
return result
return wrapper
3.2 性能测试
import time
def time_it(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} executed in {end-start:.4f} seconds")
return result
return wrapper
3.3 权限验证
def require_login(func):
def wrapper(user, *args, **kwargs):
if not user.is_authenticated:
raise PermissionError("User must be logged in")
return func(user, *args, **kwargs)
return wrapper
4. 带参数的装饰器
装饰器本身也可以接受参数:
def repeat(n):
defdecorator(func):
defwrapper(*args, **kwargs):
for _ inrange(n):
result = func(*args,**kwargs)
return result
return wrapper
return decorator
@repeat(3)
defgreet(name):
print(f"Hello {name}")
greet("Alice")
5. 类装饰器
除了函数装饰器,Python 还支持类装饰器:
class CountCalls:
def__init__(self, func):
self.func = func
self.calls = 0
def__call__(self, *args, **kwargs):
self.calls += 1
print(f"Call {self.calls} of {self.func.__name__}")
returnself.func(*args, **kwargs)
@CountCalls
defexample():
print("Inside example function")
6. 保留函数元信息
针对一个函数利用装饰器后,原函数的元信息会被替换,我们可以使用 functools.wraps 来保留函数元信息
from functools import wraps
def preserve_metadata(func):
@wraps(func)
def wrapper(*args, **kwargs):
"""Wrapper function docstring"""
return func(*args, **kwargs)
return wrapper
7. 装饰器的执行顺序
装饰器可以堆叠使用,执行顺序是从下往上:
@decorator1
@decorator2
@decorator3
def my_function():
pass
# 等效于:
my_function = decorator1(decorator2(decorator3(my_function)))
8. 实际应用示例
from functools import wraps
import time
defcache(max_size=100):
defdecorator(func):
cache_dict = {}
@wraps(func)
defwrapper(*args):
if args in cache_dict:
return cache_dict[args]
result = func(*args)
iflen(cache_dict) >= max_size:
cache_dict.popitem()
cache_dict[args] = result
return result
return wrapper
return decorator
@time_it
@cache
deffibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
9. 总结
最后总结一下 Python 装饰器的特征及用途
• 装饰器是 Python 中的高级特性,用于增强函数功能
• 使用 @decorator 语法糖来简化操作
• 可以接受参数,也可以多个装饰器一起使用
• 类也可以作为装饰器
• 可以使用 functools.wraps 保留原函数元信息
• 装饰器常用于日志、缓存、权限验证等场景
总之,装饰器可以让 Python 代码更加优雅并且可维护,是每个Python 开发者都应该掌握的重要技能