Python装饰器完全指南
编程小白的装饰器入门手册
🎯 什么是装饰器?
装饰器(Decorator)就像一个”函数包装器”,它允许你在不修改原有函数代码的情况下,给函数添加额外的功能。
📖 生活比喻:
想象你的手机是一个函数。装饰器就像手机壳:
- 📱 不需要修改手机本身
- 🔒 可以给手机添加保护功能
- 💎 随时可以更换不同的手机壳
- ✨ 手机的核心功能保持不变
装饰器的核心思想:函数也是对象,可以作为参数传递,也可以赋值给变量!
🧠 装饰器的核心概念
1. 函数是一等公民
在Python中,函数和其他数据类型(如整数、字符串)一样,可以:
- 赋值给变量
- 作为参数传递给其他函数
- 作为其他函数的返回值
# 定义一个普通函数
def greet(name):
return f”你好, {name}!”
# 将函数赋值给变量
say_hello = greet
print(say_hello(“小明”)) # 输出: 你好, 小明!
def greet(name):
return f”你好, {name}!”
# 将函数赋值给变量
say_hello = greet
print(say_hello(“小明”)) # 输出: 你好, 小明!
2. 装饰器的工作原理
装饰器本质上是一个接受函数作为参数并返回一个新函数的函数。
装饰器执行流程
1. 调用装饰器函数,并传入原始函数
2. 装饰器内部定义一个新函数(包装器)
3. 在包装器内部添加新功能并调用原始函数
4. 返回新函数替代原始函数
🔧 创建和使用装饰器
1. 基础装饰器
# 定义装饰器
def my_decorator(func):
def wrapper():
print(“函数执行前做一些事情”)
func() # 调用原始函数
print(“函数执行后做一些事情”)
return wrapper
# 使用装饰器
@my_decorator
def say_hello():
print(“大家好!”)
# 调用被装饰的函数
say_hello()
def my_decorator(func):
def wrapper():
print(“函数执行前做一些事情”)
func() # 调用原始函数
print(“函数执行后做一些事情”)
return wrapper
# 使用装饰器
@my_decorator
def say_hello():
print(“大家好!”)
# 调用被装饰的函数
say_hello()
2. 处理带有参数的函数
使用 *args 和 **kwargs 接收任意数量和类型的参数
def smart_decorator(func):
def wrapper(*args, **kwargs):
print(f”准备调用函数: {func.__name__}”)
result = func(*args, **kwargs)
print(f”函数 {func.__name__} 执行完毕”)
return result
return wrapper
@smart_decorator
def greet(name, greeting=”你好”):
return f”{greeting}, {name}!”
print(greet(“小明”, greeting=”早安”))
def wrapper(*args, **kwargs):
print(f”准备调用函数: {func.__name__}”)
result = func(*args, **kwargs)
print(f”函数 {func.__name__} 执行完毕”)
return result
return wrapper
@smart_decorator
def greet(name, greeting=”你好”):
return f”{greeting}, {name}!”
print(greet(“小明”, greeting=”早安”))
3. 带参数的装饰器
有时需要给装饰器本身传递参数(例如设置日志级别)
# 三层嵌套函数实现带参数装饰器
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def say_hello(name):
print(f”你好, {name}!”)
say_hello(“小明”)
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def say_hello(name):
print(f”你好, {name}!”)
say_hello(“小明”)
4. 类装饰器
除了函数装饰器,你还可以创建类装饰器:
class TimerDecorator:
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(f”{self.func.__name__} 执行耗时: {end_time – start_time:.4f}秒”)
return result
@TimerDecorator
def long_running_function():
total = 0
for i in range(10000000):
total += i
return total
long_running_function()
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(f”{self.func.__name__} 执行耗时: {end_time – start_time:.4f}秒”)
return result
@TimerDecorator
def long_running_function():
total = 0
for i in range(10000000):
total += i
return total
long_running_function()
💡 装饰器的常见应用场景
1. 日志记录
记录函数的执行时间、参数等信息
2. 性能测试
测量函数执行时间,用于性能优化
3. 权限验证
检查用户权限后再执行函数
4. 数据缓存
存储函数结果,避免重复计算
5. 错误处理
统一捕获和处理异常
6. 路由注册
Web框架(如Flask)中使用装饰器定义路由
⚠️ 注意事项
1. 使用 functools.wraps 保留原始函数的元信息
2. 多个装饰器的执行顺序是从下往上
3. 理解装饰器在代码导入时立即执行
🎓 总结
装饰器是Python中强大而优雅的特性
掌握装饰器可以让你写出更简洁、更灵活、更Pythonic的代码
从简单装饰器开始,逐步理解其工作原理和应用场景
装饰器让代码复用如虎添翼!