重复逻辑越来越多
同一段判断、清洗、转换逻辑在多个地方重复出现,后面越写越难统一。
代码能跑只是第一步。真正进入项目开发后,更重要的是让代码好改、好读、好复用。函数封装和工具层设计,就是把重复逻辑收起来,把通用能力沉到稳定的位置,让业务代码保持清晰。
多数难维护的代码,不一定是语法写错了,而是一开始没有设计好结构。
重复逻辑越来越多
同一段判断、清洗、转换逻辑在多个地方重复出现,后面越写越难统一。
改需求要改很多处
逻辑散落在不同位置,规则一变就要到处找,漏改一处就可能产生 bug。
不敢动旧代码
代码之间耦合太重,看不清影响范围,改一行可能牵动很多地方。
函数封装的本质,是把一段有明确输入、处理、输出的逻辑,变成一个可以反复调用的单元。
反例:同一类长度校验重复写,后面规则一变就要改多处。
user = input("输入用户名:")if len(user) < 3: print("用户名太短")
password = input("输入密码:")if len(password) < 6: print("密码太短")改法:把重复逻辑封装成函数,变化点变成参数。
def check_len(val: str, limit: int, tag: str) -> bool: if len(val.strip()) < limit: print(f"{tag}长度不足") return False return True
user = input("输入用户名:")check_len(user, 3, "用户名")
password = input("输入密码:")check_len(password, 6, "密码")这样做的价值:
| 改造点 | 带来的好处 |
|---|---|
| 逻辑只写一次 | 减少重复代码 |
| 变化点变参数 | 规则变化时更好改 |
| 函数名表达意图 | 代码更容易阅读 |
| 返回值明确 | 调用方更容易判断下一步 |
单一职责
一个函数只做一件事,拒绝把校验、读取、转换、保存全塞进一个函数。
命名清晰
函数名尽量使用“动词 + 名词”,例如 read_json、normalize_text、validate_age。
输入输出清楚
参数表示输入,返回值表示输出。必要时加类型注解,降低阅读和调用成本。
少副作用
函数尽量只做核心处理,不随便修改外部变量、打印、读写文件或发请求。
更推荐的校验函数,可以只返回判断结果,把打印提示交给外层业务流程:
def validate_name(name: str) -> bool: return 1 <= len(name.strip()) <= 20
def validate_age(age: int) -> bool: return 0 <= age <= 150当函数越来越多时,不应该全部堆在 main.py 里。入口文件应该表达业务流程,通用、可复用、无业务含义的函数,适合放进 utils 工具层。
先发现重复逻辑:比如字符串清洗、文件读取、字段校验、格式转换。
再封装成函数:让逻辑只写一次,把变化点做成参数。
最后放进工具层:如果函数不依赖具体业务,就移动到 utils 包里统一管理。
一句话定义:
适合放进 utils |
不适合放进 utils |
|---|---|
| 字符串清洗、大小写统一、空格归一化 | 用户注册、订单创建、面试报告生成 |
| 文件读写、JSON 读取、路径处理 | 直接操作业务数据库并修改业务状态 |
| 通用字段校验、格式校验 | 混合多个业务步骤的大函数 |
| 时间格式转换、金额格式化 | 依赖页面、接口、具体业务上下文的逻辑 |
一个简单项目可以这样组织:
示例:把字符串归一化逻辑放进工具层。
def normalize(text: str) -> str: return " ".join(text.strip().split()).lower()通过 utils/__init__.py 做预导入,让业务文件里的导入更短、更统一。
from .string_utils import normalize业务入口只负责调用,不关心工具函数内部怎么实现。
from utils import normalize
text = " Python is great "print(normalize(text)) # python is great