Python 函数与模块化:前端工程化思维完全通用| 基础篇

【Python 函数与模块化 + FastAPI 式工程习惯】+【AI 应用预处理与业务编排】:从【清晰接口、拆模块、包导出】到【main 入口编排与踩坑规避】,彻底搞懂可维护、可复用、可组合的 AI 业务代码 写法,避开可变默认参数、import 顶层执行、循环依赖、相对导入与启动方式等高频坑!

📑 文章目录

  • [1. 为什么"函数 + 模块化"是 AI 应用开发的地基](#1. 为什么“函数 + 模块化”是 AI 应用开发的地基)
  • [2. 函数:把"接口"写清楚,把"可读性"写出来](#2. 函数:把“接口”写清楚,把“可读性”写出来)
    • [2.1 函数到底是什么(用前端类比一下)](#2.1 函数到底是什么(用前端类比一下))
    • [2.2 推荐的函数写法:清晰命名 + docstring + 类型标注](#2.2 推荐的函数写法:清晰命名 + docstring + 类型标注)
    • [2.3 默认参数的"坑":不要写可变默认值](#2.3 默认参数的“坑”:不要写可变默认值)
  • [3. 模块化:从"文件管理"到"依赖管理"](#3. 模块化:从“文件管理”到“依赖管理”)
    • [3.1 什么是模块/包(按工程理解)](#3.1 什么是模块/包(按工程理解))
    • [3.2 模块化的目标:让你"更容易改",而不是"看着整齐"](#3.2 模块化的目标:让你“更容易改”,而不是“看着整齐”)
  • [4. 一个完整案例:写"文本清洗 + 统计 + 生成报告"的小工具(可用于 AI 输入预处理)](#4. 一个完整案例:写“文本清洗 + 统计 + 生成报告”的小工具(可用于 AI 输入预处理))
    • [4.1 目录结构(清晰到像前端 feature 目录)](#4.1 目录结构(清晰到像前端 feature 目录))
    • [4.2 模块代码](#4.2 模块代码)
    • [4.3 入口文件:main.py](#4.3 入口文件:main.py)
  • [5. 模块化踩坑清单(这些是你最可能遇到的)](#5. 模块化踩坑清单(这些是你最可能遇到的))
    • [5.1 import 会"执行文件顶层代码"](#5.1 import 会“执行文件顶层代码”)
    • [5.2 循环依赖(A import B,B 又 import A)](#5.2 循环依赖(A import B,B 又 import A))
    • [5.3 相对导入/执行方式差异导致的导入失败](#5.3 相对导入/执行方式差异导致的导入失败)
    • [5.4 "把所有逻辑堆在一个文件里"](#5.4 “把所有逻辑堆在一个文件里”)
  • [6. 实战规范(把"选择理由"写进你的编码习惯)](#6. 实战规范(把“选择理由”写进你的编码习惯))
    • [6.1 函数规范](#6.1 函数规范)
    • [6.2 模块规范](#6.2 模块规范)
    • [6.3 入口编排规范](#6.3 入口编排规范)
  • [7. 总结:你已经具备"AI 应用工程师"的工程骨架能力了](#7. 总结:你已经具备“AI 应用工程师”的工程骨架能力了)
  • [🔍 系列模块导航](#🔍 系列模块导航)
    • [📝 AI应用开发工程师基础篇](#📝 AI应用开发工程师基础篇)
    • [📚 系列总览](#📚 系列总览)

同学们好,我是 Eugene(尤金),一名前端出身、正在持续深耕 AI 应用开发的工程师。

(Eugene 发音 /juːˈdʒiːn/,大家怎么顺口怎么叫就好)

如果你也和曾经的我一样:

会前端、会工程化、项目经验不少,

但一提到大模型、RAG、Agent、向量库、AI 架构,感觉概念很多、路径很乱,不知道该从哪一步开始落地。

那这个系列,就是专门为你准备的。

这不是一套"只讲概念"的内容,而是一条前端工程师可执行的 AI 转型路线

从 Python 与 FastAPI,到大模型 API、Prompt、RAG、Agent、部署与架构,再到项目实战与面试就业。

我会坚持用大白话 + 工程化视角 + 真实场景来讲,

不堆玄学,不绕术语。

我们的目标很明确:

不只是"看懂 AI",而是"真正做出可上线、可维护、可扩展的 AI 应用"。


从前端转 AI 应用开发时,最容易卡住的点通常不是"数学/玄学",而是:在 Python 里该怎么写出可维护、可复用、可组合的代码

好消息是:这件事和你在前端做工程化是同一套思路------只是换成了 Python 的语法与组织方式而已。

本文只讲"日常写代码到底该怎么选、为什么这么选、踩坑会踩在哪",对象是完全把 AI 当新领域的老鸟小白:你看完能直接照着写模块、拆函数、搭出清晰的代码结构,并且知道常见坑怎么避。

1. 为什么"函数 + 模块化"是 AI 应用开发的地基

AI 应用工程里,常见流程通常长这样:

  • 输入:用户文本/对话/网页内容
  • 预处理:清洗、裁剪、去噪、提取关键信息
  • 组装:把数据拼成"提示词/请求参数"
  • 调用:请求模型(或检索)
  • 输出:格式化成可读结果、结构化返回(JSON/Markdown)

你会发现:这类流程天然适合拆成很多"小步骤",而"小步骤"在工程化里就对应:

  • 函数:一个明确的输入输出变换(像前端的纯函数/工具函数/可复用 composable)
  • 模块 :把一组相关函数放在一起(像前端的 utils/xxx.tsservices/xxx.ts
  • 包(package):把一组模块按"业务域/能力域"聚合(像前端的 feature 目录)

所以:AI 应用写得越久,你越离不开函数与模块化的基本功。

[⬆ 返回目录](#⬆ 返回目录)


2. 函数:把"接口"写清楚,把"可读性"写出来

2.1 函数到底是什么(用前端类比一下)

在前端你写过这种东西:

  • formatDate(date) -> string
  • parseQuery(url) -> { ... }
  • normalizeText(text) -> text

Python 的函数也是同样的理念:
函数就是一个"可复用的接口",通过输入得到输出。

关键不是语法,而是工程习惯:

  • 参数名清楚、类型含义明确
  • 返回值明确(尽量返回数据,而不是到处 print
  • 函数职责单一(类似组件/服务职责边界)

[⬆ 返回目录](#⬆ 返回目录)

2.2 推荐的函数写法:清晰命名 + docstring + 类型标注

下面是一个"文本清洗"的示例模块,我们后面会拆成多个文件来展示模块化。

text_tools/cleaning.py
python 复制代码
from __future__ import annotations

import re


def normalize_text(text: str) -> str:
    """
    统一文本格式:去首尾空格、把连续空白压缩为一个空格。

    参数:
        text: 原始文本

    返回:
        清洗后的文本
    """
    text = text.strip()
    # 把连续的空白字符(空格/换行/tab)压缩为一个普通空格
    text = re.sub(r"\s+", " ", text)
    return text


def limit_length(text: str, max_len: int) -> str:
    """
    限制文本长度,超出则截断。

    注意:
        这里是"简单截断",真实场景可能还需要按句子/段落截断。
    """
    if max_len <= 0:
        raise ValueError("max_len 必须是正数")
    if len(text) <= max_len:
        return text
    return text[:max_len]

这段代码体现了几个工程化点:

  • normalize_text(text: str) -> str:输入输出非常明确
  • docstring:让你 6 个月后仍能理解这函数干了什么
  • 校验 max_len:让错误更早暴露,而不是偷偷产出异常结果

[⬆ 返回目录](#⬆ 返回目录)

2.3 默认参数的"坑":不要写可变默认值

这是 Python 老坑之一。下面是错误示例(非常常见):

python 复制代码
def append_item(item, items=[]):
    items.append(item)
    return items

问题items=[] 只会在函数定义时创建一次,后续调用会"共享同一个列表"。

正确做法是用 None 作为默认值:

python 复制代码
from typing import Optional, List, TypeVar

T = TypeVar("T")

def append_item(item: T, items: Optional[List[T]] = None) -> List[T]:
    if items is None:
        items = []
    items.append(item)
    return items

前端你可能用过类似"不要用可变对象当默认参数"的坑;Python 这条同样适用。

[⬆ 返回目录](#⬆ 返回目录)


3. 模块化:从"文件管理"到"依赖管理"

3.1 什么是模块/包(按工程理解)

  • 模块(module) :一个 .py 文件
  • 包(package) :一个目录 + __init__.py(现代 Python 虽有隐式规则,但写清楚仍是好习惯)

你可以把它类比成前端:

  • .py 文件 ≈ 一个工具文件/服务文件
  • 目录包 ≈ 一个 feature/域(比如 text_tools/

[⬆ 返回目录](#⬆ 返回目录)

3.2 模块化的目标:让你"更容易改",而不是"看着整齐"

模块拆分最常见的目标不是好看,而是:

  • 改一个功能,不要牵一堆没关系的地方(低耦合)
  • 同一类能力聚在一起(高内聚)
  • 组合流程在入口统一编排(像前端路由/页面入口)

[⬆ 返回目录](#⬆ 返回目录)


4. 一个完整案例:写"文本清洗 + 统计 + 生成报告"的小工具(可用于 AI 输入预处理)

我们做一个小工具,它会:

  1. 清洗文本(normalize_text + limit_length
  2. 计算基础统计(字数/句子数/关键词)
  3. 生成报告(Markdown 字符串)

你可以把它当成 AI 应用里"调用模型前的预处理 + 结果格式化"。

4.1 目录结构(清晰到像前端 feature 目录)

text 复制代码
project/
  main.py
  text_tools/
    __init__.py
    cleaning.py
    analysis.py
    reporting.py

[⬆ 返回目录](#⬆ 返回目录)

4.2 模块代码

text_tools/analysis.py
python 复制代码
from __future__ import annotations

from collections import Counter
import re
from typing import List, Tuple


def word_count(text: str) -> int:
    """返回"单词数"(这里用空格切分,简单可改)。"""
    text = text.strip()
    if not text:
        return 0
    return len(text.split(" "))


def sentence_count(text: str) -> int:
    """
    估算句子数:用 . ! ? 以及中文常见标点做简单拆分。
    更准确通常需要 NLP 或规则增强。
    """
    if not text.strip():
        return 0
    # 中文逗号/句号/问号/感叹号,这里做一个基础规则
    parts = re.split(r"[.!?!?。]+", text)
    parts = [p.strip() for p in parts if p.strip()]
    return len(parts)


def top_keywords(text: str, k: int = 5) -> List[Tuple[str, int]]:
    """
    返回出现次数最多的 k 个关键词(这里做了极简规则:只保留"字母/数字/汉字")。
    """
    if k <= 0:
        raise ValueError("k 必须是正数")

    # 提取 token:汉字/字母/数字
    tokens = re.findall(r"[\u4e00-\u9fffA-Za-z0-9]+", text.lower())
    if not tokens:
        return []

    counter = Counter(tokens)
    return counter.most_common(k)

text_tools/reporting.py
python 复制代码
from __future__ import annotations

from typing import List, Tuple


def build_report(
    original: str,
    cleaned: str,
    stats: dict,
    top_kws: List[Tuple[str, int]],
) -> str:
    """
    把统计信息组装成 Markdown 报告。
    """
    lines = []
    lines.append("# 文本分析报告")
    lines.append("")
    lines.append("## 原始输入")
    lines.append(original if original else "(空)")
    lines.append("")
    lines.append("## 清洗后文本")
    lines.append(cleaned if cleaned else "(空)")
    lines.append("")
    lines.append("## 基本统计")
    for key, value in stats.items():
        lines.append(f"- {key}: {value}")
    lines.append("")
    lines.append("## Top Keywords")
    if not top_kws:
        lines.append("(无关键词)")
    else:
        for kw, cnt in top_kws:
            lines.append(f"- {kw}: {cnt}")
    lines.append("")
    return "\n".join(lines)

text_tools/__init__.py(导出公共 API,像前端 index.ts)
python 复制代码
from .cleaning import limit_length, normalize_text
from .analysis import sentence_count, top_keywords, word_count
from .reporting import build_report

__all__ = [
    "normalize_text",
    "limit_length",
    "word_count",
    "sentence_count",
    "top_keywords",
    "build_report",
]

这一步的意义:

当你在 main.py 里用到这些函数时,不用记住每个文件路径,依赖更清楚。

[⬆ 返回目录](#⬆ 返回目录)

4.3 入口文件:main.py

main.py
python 复制代码
from __future__ import annotations

from text_tools import (
    normalize_text,
    limit_length,
    word_count,
    sentence_count,
    top_keywords,
    build_report,
)


def run(text: str) -> str:
    # 1) 清洗
    cleaned = normalize_text(text)
    cleaned = limit_length(cleaned, max_len=200)

    # 2) 统计
    stats = {
        "word_count": word_count(cleaned),
        "sentence_count": sentence_count(cleaned),
        "char_count": len(cleaned),
    }

    # 3) 关键词
    kws = top_keywords(cleaned, k=5)

    # 4) 组装报告(输出交付给调用方)
    return build_report(
        original=text,
        cleaned=cleaned,
        stats=stats,
        top_kws=kws,
    )


if __name__ == "__main__":
    sample = "   Hello   世界! 你好?Hello   Python   Python   。  "
    report = run(sample)
    print(report)

你会发现:main.py 只做"编排/组装",不会塞满各种细节逻辑。

这很像前端页面/容器组件:把流程串起来,把复杂变换交给更小的模块。

[⬆ 返回目录](#⬆ 返回目录)


5. 模块化踩坑清单(这些是你最可能遇到的)

5.1 import 会"执行文件顶层代码"

Python 的导入机制是:导入时会执行该 .py 文件的顶层代码。

所以规范是:

  • 模块里只放函数/类/常量
  • 需要运行逻辑的入口 一定放在 if __name__ == "__main__":

否则你会遇到"导入一次结果就跑了一遍"的怪问题。

[⬆ 返回目录](#⬆ 返回目录)

5.2 循环依赖(A import B,B 又 import A)

循环依赖会导致:

  • 变量/函数拿到的是"未初始化的状态"
  • 运行时错误或行为异常

工程化处理思路:

  • 把"公共工具"抽到第三个模块(common.pyutils/
  • 或把依赖方向调整成"上层只依赖下层",避免互相 import

前端里你也见过这种:互相引用导致打包顺序和导出不稳定。

[⬆ 返回目录](#⬆ 返回目录)

5.3 相对导入/执行方式差异导致的导入失败

当你用相对导入(from .xxx import ...)时,用不同方式启动可能导致包上下文不同,进而报错。

建议策略(偏工程稳妥):

  • 项目入口用包方式启动(后续文章再展开)
  • 或尽量用明确的包名导入(例如上例的 from text_tools import ...

[⬆ 返回目录](#⬆ 返回目录)

5.4 "把所有逻辑堆在一个文件里"

这也是最常见的"工程坏味道"。

判断标准可以直接借鉴前端:

  • 一个文件里超过太多能力边界(比如清洗、统计、渲染全混)
  • 函数名虽然有,但每个函数都被上下文"强绑定"
  • 改某个统计逻辑会牵动其他逻辑

模块化的目的就是把边界切出来。

[⬆ 返回目录](#⬆ 返回目录)


6. 实战规范(把"选择理由"写进你的编码习惯)

6.1 函数规范

  • 函数尽量做到"输入 -> 输出",避免在函数内部到处 print
  • 参数命名要说明含义(例如 max_lenn 好)
  • 为非平凡参数/返回写 docstring
  • 明确校验边界:比如 k <= 0max_len <= 0 这种"应该失败的输入"就早失败

[⬆ 返回目录](#⬆ 返回目录)

6.2 模块规范

  • 一个 .py 文件只承载一类能力(清洗/分析/报告分别对应不同文件)
  • 在包 __init__.py 中导出公共 API(类似前端 index.ts 汇总)
  • 顶层只放定义,不要放运行逻辑

[⬆ 返回目录](#⬆ 返回目录)

6.3 入口编排规范

  • main.py(或框架入口)只做流程编排:调用模块函数并组织输出
  • 让"核心算法/变换"留在模块里,入口保持轻量

[⬆ 返回目录](#⬆ 返回目录)


7. 总结:你已经具备"AI 应用工程师"的工程骨架能力了

你现在需要补的不是"玄学原理",而是把工程直觉迁移到 Python:

  • 函数 = 清晰接口(像前端工具/纯函数)
  • 模块/包 = 能力边界(像前端模块目录)
  • 入口编排 = 串流程(像页面/路由/容器层)
  • 踩坑点集中在:默认参数、import 执行时机、循环依赖、运行方式差异

[⬆ 返回目录](#⬆ 返回目录)


🔍 系列模块导航

📝 AI应用开发工程师基础篇

一、《AI大模型应用开发怎么入门?认知、选型与避坑指南| 基础篇》
二、《AI 开发工程师到底是什么?| 基础篇》
三、《为什么 AI 应用开发首选 Python?|基础篇》
四、《Python + venv + VSCode:前端工程师 AI 转型入门|基础篇》
五、《Python 基础语法:7 天快速上手|基础篇》
六、《Python 数据结构:list 、 dict 、 set 对应 JS 的哪里?| 基础篇》

七、《Python 函数与模块化:前端工程化思维完全通用| 基础篇》
八、《Python 异步 async/await:为什么 AI 框架大量使用?| 基础篇》

👉 跟着系列慢慢学,把技术功底扎扎实实地打牢~

📚 系列总览

  • AI 应用开发从 0 到 1:前端转 AI 完整体系(持续更新中)

系列完结后会整理成一篇完整导航文并附上直达链接,方便大家按顺序、体系化学习。

全套内容持续更新中,敬请期待~

[⬆ 返回目录](#⬆ 返回目录)


AI 时代,真正稀缺的不是会调用一个模型接口的人,

而是能把业务、工程、架构、模型能力连接起来,做成完整产品的工程师。

前端转 AI,不是推倒重来,而是把你原有的工程化能力升级到新的技术栈里。

你过去积累的组件化、性能优化、协作规范、系统思维,都会在 AI 项目中继续产生价值。

后续我会持续更新这个系列:

覆盖基础认知、RAG、Agent、函数调用、开源模型部署、企业级架构、项目实战与面试求职,

帮你一步步从「会写页面」走向「能交付 AI 应用」。

如果这篇对你有帮助,欢迎 点赞 + 收藏 + 关注

把这套系列当作你的 AI 转型路线图,跟着节奏持续推进,你会看到非常明显的成长。

我是 Eugene,你的电子学友,我们下篇干货见~

相关推荐
萧行之3 小时前
Ubuntu Node.js 版本管理工具 n 完整安装与使用教程
linux·前端
星晨雪海3 小时前
企业标准 DTO 传参 + Controller + Service + 拷贝工具类完整版
java·开发语言·python
yuanmazhiwu3 小时前
计算机毕业设计:Python全国空气质量与气象监测平台 Flask框架 可视化 数据分析 机器学习 天气 深度学习 AI 空气质量分析(建议收藏)✅
人工智能·python·深度学习·数据挖掘·flask·汽车·课程设计
devlei9 小时前
从源码泄露看AI Agent未来:深度对比Claude Code原生实现与OpenClaw开源方案
android·前端·后端
Jagger_10 小时前
周末和AI肝了两天,终于知道:为什么要把AI当做实习生
前端
weixin_4561648310 小时前
vue3 子组件向父组件传参
前端·vue.js
Mr_Xuhhh10 小时前
Java泛型进阶:从基础到高级特性完全指南
开发语言·windows·python
沉鱼.4410 小时前
第十二届题目
java·前端·算法
Setsuna_F_Seiei11 小时前
CocosCreator 游戏开发 - 多维度状态机架构设计与实现
前端·cocos creator·游戏开发