Python 进阶 - 第十八节
📋 本节要点
| 知识点 | 说明 |
|---|---|
| 装饰器 | 增强函数功能的函数 |
@ 语法糖 |
装饰器的简洁写法 |
*args, **kwargs |
装饰带参数的函数 |
wraps |
保留原函数名称和文档 |
| 带参数装饰器 | 三层嵌套,接收参数配置 |
| 多个装饰器叠加 | 从上往下执行 |
1. 装饰器是什么?
装饰器是本身也是一个函数,可以在不修改原函数代码的前提下,给原函数添加额外功能。
1.1 基本结构
def 装饰器函数名称(func):
def wrapper():
# 执行原函数前的操作
func()
# 执行原函数后的操作
return wrapper
1.2 不使用装饰器 vs 使用装饰器
def my_decorator(func):
def wrapper():
print("===开始===")
func()
print("===结束===")
return wrapper
def say_hello1():
print("你好!")
# 不使用装饰器
say_hello1() # 你好!
# 使用装饰器
say_hello1 = my_decorator(say_hello1)
say_hello1()
# ===开始===
# 你好!
# ===结束===
2. @ 语法糖
@装饰器名称 是装饰器的简洁写法,等价于 func = decorator(func)。
@my_decorator # 等价于 say_hello2 = my_decorator(say_hello2)
def say_hello2():
print("你好!")
say_hello2()
# ===开始===
# 你好!
# ===结束===
3. 装饰带参数的函数
使用 *args, **kwargs 让装饰器能处理任意参数的函数:
def timer_decorator(func):
def wrapper(*args, **kwargs):
import time
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"函数 {func.__name__} 执行时间:{end - start:.4f} 秒")
return result
return wrapper
@timer_decorator
def add(a, b):
return a + b
@timer_decorator
def greet(name):
print(f"你好,{name}!")
result = add(1, 2) # 函数 add 执行时间:0.0000 秒
greet("张三") # 你好,张三!\n函数 greet 执行时间:0.0000 秒
4. 保留原函数信息
装饰后函数名会变成 wrapper,用 functools.wraps 修复:
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("调用函数前")
result = func(*args, **kwargs)
print("调用函数后")
return result
return wrapper
@my_decorator
def say_hello():
"""这是 say_hello 函数的文档"""
print("你好!")
print(say_hello.__name__) # say_hello(而不是 wrapper)
print(say_hello.__doc__) # 这是 say_hello 函数的文档
5. 带参数的装饰器
如果装饰器本身需要接收参数,需要再包一层函数——三层嵌套结构。
def repeat(times):
def decorator(func): # 接收函数
@functools.wraps(func)
def wrapper(*args, **kwargs): # 增强逻辑
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(times=3)
def say_hello():
print("你好!")
say_hello() # 你好!(打印 3 次)
6. 多个装饰器叠加
多个装饰器可以叠加使用,执行顺序从上往下。
def decorator1(func):
def wrapper(*args, **kwargs):
print("装饰器1 - 开始")
result = func(*args, **kwargs)
print("装饰器1 - 结束")
return result
return wrapper
def decorator2(func):
def wrapper(*args, **kwargs):
print("装饰器2 - 开始")
result = func(*args, **kwargs)
print("装饰器2 - 结束")
return result
return wrapper
@decorator1
@decorator2
def say_hello():
print("你好!")
say_hello()
# 装饰器1 - 开始
# 装饰器2 - 开始
# 你好!
# 装饰器2 - 结束
# 装饰器1 - 结束
7. 实战:权限验证
import functools
def requires_auth(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
is_logged_in = False # 模拟登录状态
if is_logged_in:
return func(*args, **kwargs)
else:
print("请先登录!")
return None
return wrapper
@requires_auth
def view_profile():
print("查看个人资料")
@requires_auth
def edit_profile():
print("编辑个人资料")
view_profile() # 请先登录!
edit_profile() # 请先登录!
下一节预告:生成器与迭代器
评论区
0 条暂时还没有评论,欢迎来抢沙发。