引言
在Python中,装饰器(Decorator)是一种强大的工具,它使用简单的@
符号语法,却能实现令人惊叹的代码增强功能。
装饰器初体验
1.1 最简单的装饰器示例
python
def simple_decorator(func):
def wrapper():
print("函数执行前...")
func()
print("函数执行后...")
return wrapper
@simple_decorator
def say_hello():
print("Hello!")
say_hello()
"""
输出:
函数执行前...
Hello!
函数执行后...
"""
1.2 装饰器的本质
装饰器本质上是一个高阶函数,它:
- 接受一个函数作为参数
- 返回一个新函数
- 通常在不修改原函数代码的情况下增强其功能
@decorator
只是语法糖,等价于:
python
def say_hello(): ...
say_hello = decorator(say_hello)
为什么需要装饰器?
2.1 代码复用:DRY原则
避免重复代码(Don't Repeat Yourself):
python
import time
# 没有装饰器的重复代码
def funco1():
start = time.time()
# 函数逻辑...
time.sleep(2)
end = time.time()
print(f"函数 {funco1.__name__} 耗时: {end-start}秒")
def funco2():
start = time.time()
# 函数逻辑...
time.sleep(3)
end = time.time()
print(f"函数 {funco2.__name__} 耗时: {end-start}秒")
def timing(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"函数 {func.__name__} 耗时: {end-start}秒")
return result
return wrapper
@timing
def func1():
# 函数逻辑...
time.sleep(2)
print('func1 ....')
@timing
def func2():
time.sleep(3)
# 函数逻辑...
print('func2 ....')
if __name__ == '__main__':
funco1()
funco2()
func1()
func2()
2.2 分离关注点
将业务逻辑与横切关注点(如日志、权限检查)分离:
python
@login_required
@log_execution
def delete_user(user_id):
# 纯业务逻辑
...
装饰器进阶用法
3.1 带参数的装饰器
python
def repeat(num_times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(num_times=3)
def greet(name):
print(f"Hello {name}")
greet("Alice")
"""
Hello Alice
Hello Alice
Hello Alice
"""
3.2 保留原函数元信息
使用functools.wraps
保持原函数的__name__
等属性:
python
from functools import wraps
def logged(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"调用 {func.__name__}")
return func(*args, **kwargs)
return wrapper
3.3 类装饰器
python
class CountCalls:
def __init__(self, func):
self.func = func
self.num_calls = 0
def __call__(self, *args, **kwargs):
self.num_calls += 1
print(f"调用次数: {self.num_calls}")
return self.func(*args, **kwargs)
@CountCalls
def say_hello():
print("Hello!")
say_hello() # 输出调用次数和Hello!
say_hello() # 输出调用次数和Hello!
"""
调用次数: 1
Hello!
调用次数: 2
Hello!
"""
结语
点个赞,关注我获取更多实用 Python 技术干货!如果觉得有用,记得收藏本文!