Python装饰器:魔法般的代码“外挂”,让你的函数更强大!
你是否曾想过,在不修改原有函数代码的情况下,给它增加新功能?就像给游戏角色穿上装备,属性立刻提升!这就是Python装饰器的魔力所在。
什么是装饰器?
简单来说,装饰器就是一个返回函数的函数,它接受一个函数作为参数,并返回一个新的函数。
想象一下,你有一个普通的咖啡(函数):
1 2
| def coffee(): print("一杯普通咖啡")
|
现在你想给它加点糖和奶(装饰器功能),但不想改变咖啡本身的配方。
基础装饰器:从零开始理解
让我们先看一个最简单的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13
| def sugar_decorator(func): def wrapper(): print("加一勺糖") func() print("搅拌一下") return wrapper
@sugar_decorator def coffee(): print("一杯普通咖啡")
coffee()
|
输出:
看!我们没有修改coffee函数的代码,却给它增加了新功能。
装饰器语法糖:@符号的魔法
@sugar_decorator 实际上等价于:
1
| coffee = sugar_decorator(coffee)
|
Python的@语法让代码更加简洁优雅!
处理带参数的函数
如果原函数有参数怎么办?别担心,装饰器也能处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| def log_decorator(func): def wrapper(*args, **kwargs): print(f"开始执行函数: {func.__name__}") print(f"参数: {args}, {kwargs}") result = func(*args, **kwargs) print(f"函数执行完毕") return result return wrapper
@log_decorator def add(a, b): return a + b
print(add(3, 5))
|
输出:
1 2 3 4
| 开始执行函数: add 参数: (3, 5), {} 函数执行完毕 8
|
*args和**kwargs让我们可以处理任意参数的函数,这就是装饰器的强大之处!
实际应用场景
1. 性能测试装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import time
def timer_decorator(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"{func.__name__} 执行时间: {end_time - start_time:.4f}秒") return result return wrapper
@timer_decorator def heavy_calculation(n): return sum(i*i for i in range(n))
heavy_calculation(1000000)
|
2. 权限验证装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| def login_required(func): def wrapper(user, *args, **kwargs): if not user.get('is_login', False): print("请先登录!") return None return func(user, *args, **kwargs) return wrapper
@login_required def view_profile(user): print(f"欢迎 {user['name']} 查看个人资料")
user1 = {'name': '小明', 'is_login': True} user2 = {'name': '小红', 'is_login': False}
view_profile(user1) view_profile(user2)
|
3. 缓存装饰器(记忆化)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| def cache_decorator(func): cache = {} def wrapper(n): if n not in cache: cache[n] = func(n) print(f"计算 fibonacci({n})") else: print(f"使用缓存: fibonacci({n})") return cache[n] return wrapper
@cache_decorator def fibonacci(n): if n <= 1: return n return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
|
带参数的装饰器
有时候我们希望装饰器本身也能接受参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| def repeat(times): """重复执行函数指定次数""" def decorator(func): def wrapper(*args, **kwargs): results = [] for i in range(times): print(f"第{i+1}次执行") result = func(*args, **kwargs) results.append(result) return results return wrapper return decorator
@repeat(times=3) def greet(name): print(f"你好,{name}!") return f"已问候{name}"
greet("世界")
|
类装饰器:更强大的封装
除了函数装饰器,我们还可以使用类来实现装饰器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class CounterDecorator: def __init__(self, func): self.func = func self.count = 0 def __call__(self, *args, **kwargs): self.count += 1 print(f"{self.func.__name__} 被调用了第{self.count}次") return self.func(*args, **kwargs)
@CounterDecorator def say_hello(): print("Hello!")
say_hello() say_hello() say_hello()
|
注意事项和最佳实践
保留元信息:使用functools.wraps保持原函数信息
1 2 3 4 5 6 7
| from functools import wraps
def my_decorator(func): @wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper
|
装饰器顺序很重要:
1 2 3 4 5
| @decorator1 @decorator2 def func(): pass
|
避免过度使用:装饰器虽好,但不要滥用,以免降低代码可读性
总结
装饰器是Python中强大而优雅的特性,它遵循了开放封闭原则(对扩展开放,对修改封闭)。通过装饰器,我们可以:
- ✅ 在不修改源代码的情况下增强函数功能
- ✅ 实现代码的复用和分离
- ✅ 保持代码的整洁和可读性
- ✅ 轻松实现AOP(面向切面编程)
记住这个核心:装饰器 = 接受函数作为参数 + 返回新函数
下次当你发现多个函数需要相同的前置或后置处理时,不妨考虑使用装饰器这个”代码外挂”!
练习时间:尝试为自己写一个装饰器,用来记录函数的执行日志到文件中。分享你的实现到评论区吧!
#Python #编程技巧 #装饰器 #代码优化 #Python进阶