1. 函数修饰符:不用改代码,给函数“加buff” 🎮
关键字
:函数修饰符、@语法、包装函数内容详解: 函数修饰符(也叫“装饰器”)是Python的“黑科技”——不用修改函数的代码,就能给它
新增功能
(比如计时、日志、权限校验)。 类比:函数是“一件T恤”,修饰符是“外套”——穿上外套(加修饰符),T恤本身没变,但多了“保暖/防晒”的功能! 写法是用
@修饰符名
放在函数定义上面,比如:
# 定义修饰符(外套)
def my_decorator(func):
# 定义包装函数(外套的功能)
def wrapper():
print("外套:函数执行前的准备工作~")
func() # 调用原函数(T恤)
print("外套:函数执行后的收尾工作~")
return wrapper
# 给函数穿外套
@my_decorator
def say_hello():
print("T恤:Hello World!")
# 调用函数
say_hello()
运行结果:
外套:函数执行前的准备工作~
T恤:Hello World!
外套:函数执行后的收尾工作~
原函数
say_hello
的代码没改,但多了“前后打印”的功能——这就是修饰符的魔力!
二、核心逻辑:修饰符是“函数套函数”
2. 修饰符的本质:函数当参数,返回新函数 🧠
关键字
:高阶函数、包装函数、闭包 内容详解: 修饰符的核心是
高阶函数
(把函数当参数,返回新函数),流程是:
- 定义修饰符函数(比如
my_decorator),接收原函数func当参数; - 在修饰符里定义
wrapper(包装函数),写“新增功能+调用原函数”; - 修饰符返回
wrapper——所以被修饰的函数,实际执行的是wrapper。
前面的
@my_decorator
等价于:
say_hello = my_decorator(say_hello)
——把原函数“替换”成包装后的新函数!
三、实战1:给函数加“计时功能”
3. 实用修饰符:给函数加“执行时间统计” ⏱️
关键字
:计时修饰符、通用功能 内容详解: 写一个修饰符,统计任意函数的执行时间——不用给每个函数写计时代码:
import time
# 定义计时修饰符
def time_it(func):
def wrapper(*args, **kwargs): # *args和**kwargs接收任意参数
start = time.time() # 开始时间
result = func(*args, **kwargs) # 调用原函数,传参数
end = time.time() # 结束时间
print(f"函数{func.__name__}执行时间:{end - start:.4f}秒")
return result # 返回原函数的结果
return wrapper
# 给计算函数穿“计时外套”
@time_it
def calculate_sum(n):
total = 0
for i in range(n):
total += i
return total
# 调用函数,自动计时
sum_result = calculate_sum(1000000)
print("计算结果:", sum_result)
运行后会输出:
函数calculate_sum执行时间:0.0456秒
——这个修饰符可以给
任意函数
用,复用性拉满!
四、实战2:Web应用的“登录校验修饰符”
4. Web场景:用修饰符做“登录权限校验” 🕸️
关键字
:Flask修饰符、权限校验 内容详解: 在Flask Web应用中,用修饰符限制“未登录用户不能访问某些页面”——不用在每个视图函数里写校验:
from flask import Flask, session, redirect, url_for
app = Flask(__name__)
app.secret_key = "your_secret_key" # 会话加密密钥
# 定义“登录校验”修饰符
def login_required(func):
def wrapper(*args, **kwargs):
# 检查session里是否有user_id(代表已登录)
if "user_id" not in session:
return redirect(url_for("login")) # 未登录则跳转到登录页
return func(*args, **kwargs) # 已登录则执行原函数
return wrapper
# 登录页:不用校验
@app.route("/login")
def login():
session["user_id"] = 1 # 模拟登录,写入session
return "登录成功!"
# 个人中心:需要登录校验(加修饰符)
@app.route("/profile")
@login_required
def profile():
return "个人中心页面(已登录才能看)"
if __name__ == "__main__":
app.run(debug=True)
现在访问
/profile
:
- 未登录时,自动跳转到
/login; - 登录后,才能看到个人中心——修饰符把“权限校验”逻辑统一封装,视图函数更简洁!
五、进阶:带参数的修饰符
5. 高阶玩法:带参数的修饰符——更灵活的“外套” 🎨
关键字
:带参修饰符、三层函数 内容详解: 有时候需要给修饰符传参数(比如“日志修饰符”要指定日志级别),这时候要写
三层函数
:
def log_with_level(level):
# 第一层:接收修饰符的参数
def decorator(func):
# 第二层:接收原函数
def wrapper(*args, **kwargs):
# 第三层:包装逻辑(用level参数)
print(f"[{level}] 函数{func.__name__}开始执行")
result = func(*args, **kwargs)
print(f"[{level}] 函数{func.__name__}执行结束")
return result
return wrapper
return decorator
# 给函数加“INFO级别日志”的修饰符
@log_with_level(level="INFO")
def add(a, b):
return a + b
# 调用函数
print(add(2, 3))
运行结果:
[INFO] 函数add开始执行
[INFO] 函数add执行结束
5
带参修饰符让“外套”能定制功能(比如换日志级别),灵活性更高!
六、修饰符的价值:代码复用+解耦
6. 划重点:修饰符的核心优势 🚀
关键字
:代码复用、逻辑解耦、简洁性 内容详解: 修饰符之所以强大,是因为它解决了“重复逻辑分散”的问题:
- 📦 代码复用:把“计时、日志、权限校验”等通用逻辑写成修饰符,任意函数都能复用;
- 🔌 逻辑解耦:业务逻辑(比如计算、页面渲染)和通用逻辑(比如计时)分开,代码更清晰;
- 📝 代码简洁:不用给每个函数写重复代码,加个
@修饰符就搞定。
这也是Python中“面向切面编程(AOP)”的体现——在不修改核心代码的前提下,给函数“切面式”地增加功能!