python装饰器
Python装饰器(Decorator)详解
装饰器是Python中一个非常强大且灵活的功能,广泛应用于日志记录、权限校验、性能测试、缓存等场景。理解装饰器的原理和用法,能让你的代码更加优雅和高效。
目录
- 什么是装饰器?
- 装饰器的基本原理
- 如何定义和使用装饰器
- 带参数的装饰器
- 多层装饰器
- 使用
functools.wraps
保持函数元信息 - 装饰器的应用场景
- 小结
什么是装饰器?
装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数,从而在不修改原函数代码的情况下,增强或改变函数的行为。
简单来说,装饰器就是“包装”函数的工具。
装饰器的基本原理
假设有一个函数func
,我们想在调用它之前和之后打印日志:
def func():
print("函数执行中")
def wrapper():
print("开始执行")
func()
print("执行结束")
wrapper()
这段代码实现了功能,但如果想用装饰器写法:
def decorator(func):
def wrapper():
print("开始执行")
func()
print("执行结束")
return wrapper
@decorator
def func():
print("函数执行中")
func()
@decorator
语法等价于func = decorator(func)
,调用func()
时实际上调用的是wrapper()
。
如何定义和使用装饰器
简单装饰器示例
def decorator(func):
def wrapper():
print("调用前")
func()
print("调用后")
return wrapper
@decorator
def say_hello():
print("Hello!")
say_hello()
输出:
调用前
Hello!
调用后
带参数的装饰器
如果被装饰的函数有参数,装饰器内部的wrapper
也需要接收参数:
def decorator(func):
def wrapper(*args, **kwargs):
print("调用前")
result = func(*args, **kwargs)
print("调用后")
return result
return wrapper
@decorator
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
多层装饰器
一个函数可以被多个装饰器装饰,装饰器会从内到外依次调用:
def deco1(func):
def wrapper():
print("deco1 start")
func()
print("deco1 end")
return wrapper
def deco2(func):
def wrapper():
print("deco2 start")
func()
print("deco2 end")
return wrapper
@deco1
@deco2
def say():
print("Say something")
say()
输出:
deco1 start
deco2 start
Say something
deco2 end
deco1 end
使用functools.wraps
保持函数元信息
装饰器会覆盖原函数的__name__
、__doc__
等属性,使用functools.wraps
可以保持原函数信息:
import functools
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("调用前")
return func(*args, **kwargs)
return wrapper
@decorator
def greet():
"""打招呼函数"""
print("Hello!")
print(greet.__name__) # greet
print(greet.__doc__) # 打招呼函数
装饰器的应用场景
- 日志记录:自动打印函数调用日志
- 权限校验:检查用户权限,控制访问
- 性能测试:统计函数执行时间
- 缓存:缓存函数结果,避免重复计算
- 输入校验:验证函数参数合法性
小结
- 装饰器是接受函数并返回新函数的高阶函数。
- 使用
@decorator
语法糖简化装饰器应用。 - 支持带参数函数和多层装饰器。
- 使用
functools.wraps
保持函数元信息。 - 装饰器广泛应用于代码增强和功能复用。