4.2 KiB
Day_3 · 函数与异常:后端程序的"骨架"和"安全网"
后端代码里出现频率最高的两个技巧:把函数当参数传来传去(日志、中间件的底层) 和 异常处理(参数校验、错误响应的底层)。 今天两道题都只用到基础语法,做完你就掌握了后端开发的两块地基。
今日知识点 → 以后在 Django / Celery 里对应什么
| 今天练的 | 以后在 Django/Celery 里会看到 |
|---|---|
函数作为参数、*args/**kwargs |
视图函数 def index(request, **kwargs)、中间件、Celery 任务 |
| 自定义异常 + try/except | Http404、ValidationError、Celery 任务失败与重试 |
题目一(必做):万能日志记录器(函数 + *args/**kwargs)
背景:后端程序要记录"哪个函数被调用了、用了多久",这叫日志(logging)。 Django 中间件、Celery 任务、接口调用统计里,到处都是这种"给函数包一层"的操作。
要求:写函数 log_call(func),它接收一个函数作为参数,返回一个新函数。
新函数在被调用时:
- 打印
[LOG] 调用函数 <函数名>,参数为 args=(...), kwargs={...} - 调用原函数,拿到结果
- 打印
[LOG] <函数名> 执行完成,耗时 x.xxxx 秒(用time.time()算耗时) - 返回原函数的结果
参数要用 *args 和 **kwargs 打包——因为你不知道原函数会接收什么参数。
示例
import time
def add(a, b):
return a + b
logged_add = log_call(add)
print(logged_add(1, 2))
# [LOG] 调用函数 add,参数为 args=(1, 2), kwargs={}
# [LOG] add 执行完成,耗时 0.0001 秒
# 3
进阶(加分):给 log_call 加第二个参数 label(默认空字符串),
打印日志时带上标签,如 log_call(add, label="核心计算") → [核心计算][LOG] ...。
提示:如果你已经看过装饰器语法,可以用
@log_call直接写在函数头上; 没学过就写成log_call(add)(1, 2)这种普通调用,两种都行。
出题意图:Django 视图函数接收 request、URL 参数通过 **kwargs 传进来;
Celery 的任务、日志中间件全部建立在"函数作为参数 + *args/**kwargs"之上。
题目二(必做):模拟注册接口的参数校验
背景:后端接口收到请求后的第一件事永远是校验参数。
字段缺失、格式不对,都要返回明确的错误信息,绝不能带着脏数据往下走。
Django 里抛 ValidationError、Celery 里任务失败后重试——这一切的起点都是 try/except。
要求:
- 定义一个字典模拟前端传来的注册数据:
data = {"username": "zhangsan", "email": "zs@163.com", "age": "20"}(注意 age 是字符串) - 自定义一个异常类
ValidationError(Exception)。 - 写函数
validate_registration(data),按以下规则校验,任何一个不满足就抛ValidationError:username必须存在且长度 ≥ 3email必须存在且同时包含@和.age必须存在、能转成 int、且1 <= age <= 120
- 在调用方用 try/except 捕获:失败打印
校验失败: <异常信息>,成功打印注册成功,欢迎 <username>!
进阶(加分):把规则本身做成数据——写一个通用函数
validate(data, rules),其中 rules 是一个字典:
{字段名: (校验函数, 错误信息)},返回所有不满足的字段的错误列表。
(提示:校验函数就是你平时写的普通函数或 lambda。)
这是后端参数校验框架(比如 DRF 的 Serializer)的雏形,能想出来说明你已经开始有"抽象"的意识了。
出题意图:Django forms / serializers 的校验、Celery 任务的失败处理, 核心模式都是"校验 → 抛异常 → 上层捕获处理"。 今天的题目就是把这个模式焊死在你的肌肉记忆里。
完成标准
- 题目一能打印出完整的调用日志(含进阶则 +1)
- 题目二能对"缺字段 / 格式错 / 年龄越界"三种情况分别报错(含进阶则 +1)
完成后打开 参考解答.py 对照。建议看完后关掉文件,自己再默写一遍。