【FDE系列】阶段2:Day 35:Python + SQL — 工单接入 MySQL + 本周收官

📚前言

📒FDE系列内容总纲:

【大纲】FDE 前沿部署工程师学习系列教程-CSDN博客

🚄前置课程列表:

见文档结尾附录。


🚀阶段2·Day 35:Python + SQL --- 工单接入 MySQL + 本周收官

FDE 学习系列教程 · 第二阶段 · 第 3 周 · Day 5 预计时长:3 小时 | 难度:★★★★☆ | 前置知识:Day 31-34 全部内容
📌 一句话目标:装好 MySQL,用 SQLAlchemy 和 pandas 在 Python 里读写数据库,搭一条"脏 CSV → 清洗 → MySQL"管道,并把第 2 周的工单 API 从内存升级为 MySQL 持久化。


🧑‍🤝‍🧑 开场:从"玩具"到"真家伙"

兄弟,前四天我们都在 SQLite 上练。它轻便、零安装,是最好的训练场。但它有个天花板:不支持多人高并发,不适合当生产服务器

客户现场跑的是 MySQL------真正的企业级数据库,作为一个服务 7×24 小时跑在服务器上,成百上千个请求同时来都扛得住。

今天完成三级跳:

复制代码
  Day31-34                  今天                      最终成果
┌──────────┐          ┌──────────────┐         ┌────────────────┐
│ SQLite   │   ───►   │ MySQL 服务    │  ───►   │ FastAPI 工单API │
│ 单文件    │          │ SQLAlchemy   │         │ 数据持久化      │
│ 自己练    │          │ pandas       │         │ 重启不丢        │
└──────────┘          └──────────────┘         └────────────────┘

今天内容多,遇到安装报错别烦躁------装数据库本身就是 FDE 的必备技能,客户服务器上你也得这么干。一步步来。


🖥️ 一、安装 MySQL(Windows)

安装步骤

  1. 打开 https://dev.mysql.com/downloads/installer/ ,下载 MySQL Installer for Windows(选体积较大的那个完整版 MSI,约 400MB,组件全)

  2. 运行安装程序,安装类型选 "Server only"(只装服务器即可,体积小;想要图形界面可选 Full)

  3. 一路 Next,到配置环节:

    • Config TypeDevelopment Computer(开发机)

    • 端口(Port)保持 3306,勾上"开机自启"

    • 认证方式选推荐的 Use Strong Password Encryption

  4. 设置 root 密码 :学习阶段建议设成好记的,比如 fde2026(生产环境务必用强密码!)

  5. 点 Execute 应用配置 → Finish

验证安装成功

打开开始菜单里的 MySQL Command Line Client ,输入刚才的密码,看到 mysql> 提示符就成了:

复制代码
Enter password: ********
Welcome to the MySQL monitor.
mysql>

⚠️ 两个信息务必记牢,后面 Python 连接全靠它们:

  • 用户名 root,密码 fde2026(你自己设的)

  • 端口 3306

装不上的常见原因:① 3306 端口被别的程序占了(之前装过 MySQL/MariaDB)② 缺少 Visual C++ 运行库(按提示装一个即可)。


🖥️ 二、建库建表

在 MySQL Command Line 里逐段执行(注意 MySQL 的语法和 SQLite 略有不同):

复制代码
-- ① 创建数据库(指定 utf8mb4 字符集,才能正确存中文和 emoji)
CREATE DATABASE IF NOT EXISTS fde_tickets
    CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE fde_tickets;

-- ② 工程师表
CREATE TABLE engineers (
    id         INT AUTO_INCREMENT PRIMARY KEY,
    name       VARCHAR(50) NOT NULL,
    phone      VARCHAR(20),
    department VARCHAR(50),
    title      VARCHAR(50) DEFAULT '工程师',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- ③ 设备表(DECIMAL 定点数存温度,比浮点精确)
CREATE TABLE devices (
    id          INT AUTO_INCREMENT PRIMARY KEY,
    name        VARCHAR(50) NOT NULL,
    type        VARCHAR(20) NOT NULL,
    temperature DECIMAL(5,1) DEFAULT 0,
    vibration   DECIMAL(4,1) DEFAULT 0,
    is_running  BOOLEAN DEFAULT TRUE,
    engineer_id INT,
    created_at  DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (engineer_id) REFERENCES engineers(id)
);

-- ④ 工单表
CREATE TABLE tickets (
    id          INT AUTO_INCREMENT PRIMARY KEY,
    device_id   INT NOT NULL,
    title       VARCHAR(200) NOT NULL,
    priority    VARCHAR(10) DEFAULT '中',
    status      VARCHAR(20) DEFAULT '待处理',
    reporter_id INT,
    created_at  DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (device_id)   REFERENCES devices(id),
    FOREIGN KEY (reporter_id) REFERENCES engineers(id)
);

-- 看一眼表建好了没
SHOW TABLES;

SQLite → MySQL 数据类型对照

含义 SQLite MySQL
整数 INTEGER INT / BIGINT
小数 REAL DECIMAL(5,1) / FLOAT / DOUBLE
字符串 TEXT VARCHAR(50) / TEXT
布尔 INTEGER(0/1) BOOLEAN / TINYINT(1)
时间 TEXT DATETIME / TIMESTAMP
自增主键 AUTOINCREMENT AUTO_INCREMENT

💡 DECIMAL(5,1) 是啥意思? 总共 5 位数字,小数部分占 1 位,所以整数部分最多 4 位------能存 -9999.99999.9。温度用定点数而非 FLOAT,是为了避免浮点误差(0.1+0.2≠0.3 的老问题)。涉及金额必须用 DECIMAL。


🖥️ 三、安装 Python 库

在你的项目虚拟环境里:

复制代码
pip install sqlalchemy pymysql pandas

三个库分工明确:

角色 大白话
sqlalchemy ORM / 数据库工具包 Python 和数据库之间的"万能翻译官"
pymysql MySQL 驱动 让 Python 能说 MySQL 的"方言"
pandas 数据分析库 一张表在 Python 里变成强大的 DataFrame
复制代码
  你的 Python 代码
       │
       ▼
  SQLAlchemy(统一接口,换数据库只改连接串)
       │
       ▼
  PyMySQL(MySQL 专用驱动)
       │
       ▼
  MySQL 服务器(3306 端口)

💡 连接串(URL)是关键,格式背下来:

复制代码
mysql+pymysql://用户名:密码@主机:端口/数据库名?charset=utf8mb4
mysql+pymysql://root:fde2026@localhost:3306/fde_tickets?charset=utf8mb4

mysql+pymysql 的意思是"用 pymysql 驱动连 MySQL"。charset=utf8mb4 保证中文不乱码。


🖥️ 四、SQLAlchemy 连接与操作

新建 07_sqlalchemy.py

复制代码
"""
SQLAlchemy 操作 MySQL
文件:07_sqlalchemy.py
"""
from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker

# ① 创建引擎(整个程序通常只创建一次,它内部管连接池)
engine = create_engine(
    "mysql+pymysql://root:fde2026@localhost:3306/fde_tickets?charset=utf8mb4",
    echo=True,          # echo=True 打印实际执行的 SQL,学习时强烈建议开
    pool_pre_ping=True  # 连接前探活,避免用到断开的旧连接
)

# ② 用 with 管理连接(自动关闭,不用手写 close)
with engine.connect() as conn:
    # 插入工程师 ------ 参数用 :名字 占位(SQLAlchemy 风格,防注入)
    conn.execute(text("""
        INSERT INTO engineers (name, phone, department, title)
        VALUES (:name, :phone, :dept, :title)
    """), [
        {"name": "李工", "phone": "13800001111", "dept": "一车间", "title": "高级工程师"},
        {"name": "王工", "phone": "13800002222", "dept": "二车间", "title": "工程师"},
        {"name": "赵工", "phone": "13800003333", "dept": "一车间", "title": "工程师"},
    ])
    conn.commit()

    # 查询
    result = conn.execute(text("SELECT id, name, department FROM engineers"))
    print("\n工程师列表:")
    for row in result:
        print(f"  {row.id}. {row.name} | {row.department}")

运行:

复制代码
python 07_sqlalchemy.py

echo=True 会让你看到 SQLAlchemy 实际发出的 SQL 语句------这是学习"Python 代码如何变成 SQL"的最佳窗口。熟悉后在生产代码里关掉(echo=False)。

📌 参数占位符的演变

  • SQLite 原生驱动:?

  • MySQL 原生驱动(pymysql):%s

  • SQLAlchemy 统一用 :名字(命名参数),不管底层啥数据库都一样

这就是用 SQLAlchemy 的一大好处:换数据库时业务代码几乎不动,只改连接串。

pandas 读写数据库(爽到飞起)

在同一文件追加:

复制代码
import pandas as pd

# 读:一句 SQL → DataFrame(带表头的二维表,类似 Excel)
df = pd.read_sql("SELECT * FROM engineers", engine)
print("\npandas 读出来的:")
print(df)

# 写:DataFrame → 数据库表,一行搞定
new_devices = pd.DataFrame([
    {"name": "注塑机A1", "type": "注塑", "temperature": 65.0,
     "vibration": 8.0, "is_running": True, "engineer_id": 1},
    {"name": "注塑机A2", "type": "注塑", "temperature": 82.0,
     "vibration": 12.0, "is_running": True, "engineer_id": 2},
])
new_devices.to_sql("devices", engine, if_exists="append", index=False)
print(f"\n✅ pandas 写入 {len(new_devices)} 条设备")

to_sqlif_exists 三种模式必须分清:

参数值 行为 什么时候用
fail 表已存在就报错(默认,最安全) 防止误覆盖
replace 先 DROP 整表再建(数据全没! 临时表、整表重灌
append 往现有表追加数据 增量导入(最常用)

⚠️ replace 是"删表重建",不是更新!对着生产表手滑用了 replace,眼泪能流一升。日常导入用 append


🖥️ 五、数据管道:脏 CSV → pandas 清洗 → MySQL

把 Day 34 的清洗脚本升级成 MySQL 版本。新建 08_pipeline.py

复制代码
"""
数据管道:脏 CSV → pandas 清洗 → MySQL 持久化
文件:08_pipeline.py
"""
import pandas as pd
from sqlalchemy import create_engine
import logging

logging.basicConfig(level=logging.INFO,
                    format="%(asctime)s [%(levelname)s] %(message)s")
log = logging.getLogger(__name__)

engine = create_engine(
    "mysql+pymysql://root:fde2026@localhost:3306/fde_tickets?charset=utf8mb4"
)


def load_and_clean(csv_path):
    """读 CSV 并清洗,全程向量化操作,比手写循环快得多"""
    df = pd.read_csv(csv_path)
    log.info(f"原始数据:{len(df)} 行")

    # ① 标准化:设备名去空格→大写→去内部空格;负责人去空格
    df["device_name"] = df["device_name"].astype(str).str.strip()\
                                          .str.upper().str.replace(" ", "")
    df["owner_name"] = df["owner_name"].astype(str).str.strip()

    # ② 温度:中文数字映射 → 转数字(转不了的变 NaN,对应数据库 NULL)
    cn_map = {"八十二": "82", "九十": "90", "九十一": "91"}
    df["temperature"] = df["temperature"].astype(str).str.strip().replace(cn_map)
    df["temperature"] = pd.to_numeric(df["temperature"], errors="coerce")
    #                          errors="coerce" 是灵魂:无法转换的变 NaN 而不是报错

    # ③ 手机号:去横杠空格;pandas 把空读成 NaN(字符串'nan'),还原成 None
    df["phone"] = df["phone"].astype(str).str.replace("-", "", regex=False)\
                               .str.replace(" ", "", regex=False)
    df.loc[df["phone"].isin(["nan", "None", ""]), "phone"] = None

    # ④ 去重
    before = len(df)
    df = df.drop_duplicates(subset=["device_name", "owner_name"])
    log.info(f"去重:{before} → {len(df)} 行(删除 {before-len(df)} 条)")

    return df


def save_to_mysql(df, table_name):
    df.to_sql(table_name, engine, if_exists="append", index=False)
    log.info(f"✅ 写入 {table_name} 表 {len(df)} 条")


# ===== 跑管道 =====
df = load_and_clean("dirty_data.csv")
print(df)   # 直接打印 DataFrame 检查清洗效果
save_to_mysql(df, "devices_clean")

# 验证
cnt = pd.read_sql("SELECT COUNT(*) AS c FROM devices_clean", engine)
log.info(f"devices_clean 表现共 {cnt.iloc[0,0]} 条")

💡 对比 Day 34 的纯 Python 版本,pandas 的 str.strip()to_numeric(errors='coerce')drop_duplicates() 都是向量化操作------不用自己写 for 循环,一行顶十行,处理几万行 CSV 速度快几十倍。这就是为什么数据分析人人爱 pandas。
⚠️ 第一次跑前,先在 MySQL 里建 devices_clean 表(列名要和 DataFrame 对得上),或用 to_sql(..., if_exists='replace') 让 pandas 自动建表(学习阶段图省事可以,生产环境建议手动建表好控制类型)。


🖥️ 六、重头戏:工单 API 接入 MySQL(持久化)

回到第 2 周的 FastAPI 工单项目。当时数据存在内存列表里,重启就没。今天把数据层换成 MySQL。

还记得 Day 26 学的分层架构吗?现在它开始回报你了------我们只替换数据层,接口层一行不用改。

复制代码
  分层架构的回报:

  ┌─────────────────────────┐
  │  接口层 main.py(路由)   │  ← 完全不用改!
  │  @app.get("/tickets")   │
  └───────────┬─────────────┘
              │ 调用
  ┌───────────▼─────────────┐
  │  数据层 data_store.py    │  ← 只换这一层
  │  旧:内存 TICKETS 列表    │
  │  新:MySQL 增删改查      │
  └─────────────────────────┘

新建 data_store.py

复制代码
"""
数据层:MySQL 版本(替换原来的内存列表)
文件:data_store.py
"""
from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker
from contextlib import contextmanager

engine = create_engine(
    "mysql+pymysql://root:fde2026@localhost:3306/fde_tickets?charset=utf8mb4",
    pool_pre_ping=True
)
SessionLocal = sessionmaker(bind=engine)


@contextmanager
def get_db():
    """数据库会话上下文管理器:自动提交/回滚/关闭"""
    session = SessionLocal()
    try:
        yield session
        session.commit()          # 没出异常 → 提交
    except Exception:
        session.rollback()        # 出异常 → 回滚(保证不留半截脏数据)
        raise
    finally:
        session.close()           # 无论如何都关闭,归还连接给连接池


# ===== CRUD =====

def list_tickets(status=None, priority=None):
    """动态拼条件查工单列表"""
    with get_db() as db:
        sql = "SELECT * FROM tickets WHERE 1=1"   # 1=1 方便后面无脑 AND
        params = {}
        if status:
            sql += " AND status = :status"
            params["status"] = status
        if priority:
            sql += " AND priority = :priority"
            params["priority"] = priority
        sql += " ORDER BY created_at DESC"
        result = db.execute(text(sql), params)
        return [dict(row._mapping) for row in result]


def get_ticket(ticket_id):
    with get_db() as db:
        result = db.execute(
            text("SELECT * FROM tickets WHERE id = :id"), {"id": ticket_id}
        )
        row = result.fetchone()
        return dict(row._mapping) if row else None


def create_ticket(data):
    with get_db() as db:
        db.execute(text("""
            INSERT INTO tickets (device_id, title, priority, status, reporter_id)
            VALUES (:device_id, :title, :priority, '待处理', :reporter_id)
        """), data)
        new_id = db.execute(text("SELECT LAST_INSERT_ID() AS id")).fetchone()[0]
        return get_ticket(new_id)


def update_ticket(ticket_id, data):
    with get_db() as db:
        sets, params = [], {"id": ticket_id}
        for key, val in data.items():
            if val is not None:
                sets.append(f"{key} = :{key}")
                params[key] = val
        if sets:
            db.execute(text(f"UPDATE tickets SET {', '.join(sets)} WHERE id=:id"),
                       params)
        return get_ticket(ticket_id)


def delete_ticket(ticket_id):
    with get_db() as db:
        result = db.execute(text("DELETE FROM tickets WHERE id=:id"),
                            {"id": ticket_id})
        return result.rowcount > 0

几个关键设计点

1. @contextmanager 上下文管理器------数据库操作的安全护栏

复制代码
with get_db() as db:        进入时:自动开一个会话
    db.execute(INSERT)         正常 → commit() 提交
    db.execute(UPDATE)         异常 → rollback() 回滚
                           退出时:close() 一定执行(哪怕报错)

这保证了:连接不泄漏、出错不留半成品。比每次手写 try/finally 清爽。

2. WHERE 1=1 是动态拼 SQL 的经典技巧

因为查询条件是可选的(用户可能只传 status,也可能 status/priority 都传),写死 WHERE 会很麻烦。用 WHERE 1=1 打底,后面每个条件直接 AND ... 往上拼即可。

3. 列名不能用参数占位符

:参数 只能占位"值",不能占位"列名"。所以 update_ticket 里列名用 f-string 拼、值用 :参数 传。这里列名来自你自己的代码(白名单内),安全;绝不能把用户输入直接拼进 SQL。

接口层 main.py 几乎不变

复制代码
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import data_store   # ← 关键:只改这一行的 import(原来可能是内存版)

app = FastAPI(title="工单 API(MySQL 版)")

class TicketIn(BaseModel):
    device_id: int
    title: str
    priority: str = "中"
    reporter_id: int | None = None

@app.get("/tickets")
def list_tickets(status: str | None = None, priority: str | None = None):
    return data_store.list_tickets(status, priority)

@app.post("/tickets", status_code=201)
def create_ticket(t: TicketIn):
    return data_store.create_ticket(t.model_dump())

@app.get("/tickets/{ticket_id}")
def get_ticket(ticket_id: int):
    t = data_store.get_ticket(ticket_id)
    if not t:
        raise HTTPException(404, "工单不存在")
    return t

@app.delete("/tickets/{ticket_id}", status_code=204)
def delete_ticket(ticket_id: int):
    if not data_store.delete_ticket(ticket_id):
        raise HTTPException(404, "工单不存在")

见证奇迹的时刻

复制代码
uvicorn main:app --reload
  1. 用 Swagger(http://localhost:8000/docs)创建 2 张工单

  2. 关掉 uvicorn 服务(Ctrl+C)

  3. 重新启动 uvicorn main:app --reload

  4. 再查 GET /tickets------数据还在!

这就是持久化。在 MySQL Command Line 里也能直接查到:

复制代码
USE fde_tickets;
SELECT * FROM tickets;

📌 这一刻你应该体会到分层架构的价值:换数据层(内存→MySQL),接口层、Pydantic 模型、文档全部零修改。以后要从 MySQL 换成 PostgreSQL?改个连接串的事。这就是 Day 26 埋的伏笔在今天开花结果。


📝 本周复习:知识地图

复制代码
SQL 与数据处理(Day 31-35)
│
├─ 基础 CRUD(Day 31)
│   ├─ SQLite 上手 + DBeaver 可视化
│   ├─ SELECT / WHERE / ORDER BY / LIMIT
│   ├─ INSERT / UPDATE / DELETE(写操作必加 WHERE!)
│   ├─ 主键、数据类型、? 占位符防注入
│   └─ commit 落盘
│
├─ 多表查询(Day 32)
│   ├─ 为什么拆表:消除重复,一处改处处生效
│   ├─ 主键 / 外键 / 表关系(1:N)
│   ├─ INNER JOIN(交集)/ LEFT JOIN(左全保留补 NULL)
│   ├─ 聚合 COUNT/SUM/AVG/MAX/MIN + GROUP BY
│   ├─ HAVING 过滤组(WHERE 过滤行)
│   └─ 执行顺序 FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY→LIMIT
│
├─ 进阶查询(Day 33)
│   ├─ 子查询 / CTE(WITH,把复杂查询拆成流水线)
│   ├─ ROW_NUMBER / RANK / DENSE_RANK 的区别
│   ├─ PARTITION BY:分组但不压扁行
│   ├─ 组内 TopN 模板:CTE + ROW_NUMBER + WHERE rn<=N
│   └─ SUM/AVG OVER(PARTITION BY):每行带组统计
│
├─ 数据清洗(Day 34)
│   ├─ 四类脏数据:重复 / 缺失 / 格式不一致 / 类型异常
│   ├─ 顺序:先标准化 → 再去重 → 后补缺转类型
│   ├─ TRIM/UPPER/REPLACE/CAST/COALESCE
│   ├─ 脱敏 SUBSTR+拼接;原始数据只读不覆盖
│   └─ 全程日志留痕
│
└─ Python + SQL(Day 35)
    ├─ MySQL 安装 + 建库建表(utf8mb4 / DECIMAL)
    ├─ 连接串 mysql+pymysql://user:pwd@host:3306/db
    ├─ SQLAlchemy engine / text(:命名参数) / 上下文管理器
    ├─ pandas read_sql() / to_sql(append/replace/fail)
    ├─ 数据管道:脏 CSV → pandas 清洗 → MySQL
    └─ 工单 API 接入 MySQL,分层架构接口层零修改

📋 本周验收清单

序号 验收项 达标标准 自测方式
1 基础查询 熟练写 SELECT+WHERE+ORDER BY+LIMIT Day31 练习 1 全对
2 增删改 会 INSERT/UPDATE/DELETE,且记得加 WHERE 能说出忘加 WHERE 的后果
3 多表 JOIN 能独立写三表关联 Day32 练习 1 跑通
4 分组统计 GROUP BY + HAVING 用对 能讲清 WHERE/HAVING 区别
5 窗口函数 写出分组 TopN Day33 练习 3 跑通
6 CTE 用 WITH 把复杂查询分段 Day33 练习 4 跑通
7 数据清洗 脏 CSV → 干净数据入库 9 行洗成 6 行且无报错
8 脱敏 手机号/身份证打码 Day34 练习 3 正确
9 Python+SQL SQLAlchemy + pandas 连 MySQL 脚本能读写真实 MySQL
10 数据管道 CSV→清洗→MySQL 一键跑通 08_pipeline.py 成功
11 API 持久化 工单 API 重启数据不丢 重启后数据仍在

全绿了吗? 有 1-2 项不踏实很正常,回看对应那天的实操再敲一遍。SQL 这东西,手上敲过和眼睛看过是两种技能


🎉 本周收官:你获得了什么

这一周,你完成了从"数据在内存里裸奔"到"企业级数据处理"的跨越:

  • 你能在数据库里设计表、写各种查询,包括多表 JOIN、分组统计、窗口排名

  • 你能把客户给的脏 CSV 洗成干净数据,还知道怎么脱敏、怎么留痕

  • 你能用 Python(SQLAlchemy + pandas)操作真正的 MySQL

  • 你的工单 API 接上了数据库,重启不丢数据,有了生产应用的雏形

    复制代码
    你现在手里的完整数据能力栈:
    
    数据源      清洗加工        存储            对外服务

    ┌────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐
    │ 脏 CSV │→│ pandas │→│ MySQL │ ←── │ FastAPI │
    │ 设备日志 │ │ 标准化 │ │ 三表关联 │ │ 工单 API │
    │ 客户 Excel│ │ 去重补缺 │ │ 索引/外键 │ │ Swagger │
    └────────┘ └──────────┘ └─────────┘ └──────────┘

这套"数据进来 → 清洗 → 入库 → 对外提供 API"的链路,就是无数企业系统的骨架。FDE 在客户现场做的数据对接,本质都是它的变体。


🔭 下阶段预告

第 3 周拿下数据,第 4 周要攻克部署环境。客户的服务器 90% 是 Linux------没有图形界面、没有资源管理器,全靠命令行。

下周你会:

  • 在 Windows 上用 WSL2 装一个 Ubuntu,拥有本地 Linux 环境

  • 掌握文件操作、权限、进程管理、文本三剑客(grep/awk/sed)

  • 写 Shell 脚本把重复操作自动化(自动备份、健康检查)

  • 用 nohup、crontab 让服务后台常驻、定时执行

你的工单 API 现在跑得好好的,但总不能一直占着你的终端窗口。下周教你怎么把它"扔到服务器上一直跑"。周末好好休息,下周进入部署工程师的世界!


🌍附录:前置课程列表

阶段一:

【FDE系列】阶段1Day 1:AI 层级关系 --- 四个嵌套的圈-CSDN博客

【FDE系列】阶段1Day 2:AI 三阶段发展史 --- 会认 → 会判断 → 会创造-CSDN博客

【FDE系列】阶段1Day 3:符号 AI vs 机器学习 --- 两条路线的本质区别-CSDN博客

【FDE系列】阶段1Day 4:Transformer 的历史意义 --- 2017 年的分水岭-CSDN博客

【FDE系列】阶段1Day 5:本周复习与自测 --- 检验你的 AI 认知地基-CSDN博客

【FDE系列】阶段1Day 6:Transformer 架构 --- 一张图纸盖出千千万万栋楼-CSDN博客

【FDE系列】阶段1Day 7:LLM 本质 --- 文字接龙机器-CSDN博客

【FDE系列】阶段1Day 8:Token --- 模型眼中的最小单位-CSDN博客

【FDE系列】阶段1Day 9:AI 幻觉 --- 为什么会一本正经地胡说八道-CSDN博客

【FDE系列】阶段1Day 10:上下文窗口 --- 模型的记忆力上限 + 本周复习-CSDN博客

【FDE系列】阶段1Day 11:Prompt --- 给模型立规矩-CSDN博客

【FDE系列】阶段1Day 12:Memory --- 让模型记住上下文

【FDE系列】阶段1Day 13:RAG --- 给模型配图书管理员-CSDN博客

【FDE系列】阶段1Day 14:Tool Use --- 让模型动手操作-CSDN博客

【FDE系列】阶段1Day 15:MCP --- 统一的工具接口标准 + 第三周复习-CSDN博客

【FDE系列】阶段1Day 16:什么是 FDE --- 把 AI 变成客户结果的人-CSDN博客

【FDE系列】阶段1Day 17:FDE vs 传统实施 --- 三大本质区别-CSDN博客

【FDE系列】阶段1Day 18:FDE 三重身份 + C6 胜任力模型-CSDN博客

【FDE系列】阶段1Day 19:七阶段行动路径 + 行业经验的价值-CSDN博客

【FDE系列】阶段1Day 20:阶段总结与产出物 --- 第一阶段收官-CSDN博客


阶段二:

【FDE系列】阶段2:Day 21:Python 环境搭建 --- 写出你的第一行代码-CSDN博客

【FDE系列】阶段2:Day 22:变量、数据类型、条件判断 --- Python 的"记忆"和"判断"-CSDN博客

【FDE系列】阶段2:Day 23:循环与函数 --- 让代码跑 100 遍、把逻辑打包复用-CSDN博客

【FDE系列】阶段2:Day 24:数据结构 --- 列表、字典、集合、元组-CSDN博客

【FDE系列】阶段2:Day 25:文件读写与 JSON --- 让程序连通外部数据(第一周收官)-CSDN博客

【FDE系列】阶段2:Day 26:模块化编程 --- 把代码拆成"抽屉柜"-CSDN博客

【FDE系列】阶段2:Day 27:异常处理与日志 --- 让程序"摔不烂、查得到"-CSDN博客

【FDE系列】阶段2:Day 28:FastAPI 入门 --- 把你的函数变成 API 服务-CSDN博客

【FDE系列】阶段2:Day 29:FastAPI 进阶 --- Pydantic 模型与完整 CRUD 实战-CSDN博客

【FDE系列】阶段2:Day 30:生产代码规范 --- 测试、类型注解、配置管理(第二周收官)-CSDN博客

【FDE系列】阶段2:Day 31:SQL 基础 --- 增删改查一把梭-CSDN博客

【FDE系列】阶段2:Day 32:多表查询 --- JOIN 与聚合-CSDN博客

【FDE系列】阶段2:Day 33:进阶查询 --- 窗口函数与 CTE-CSDN博客

【FDE系列】阶段2:Day 34:数据清洗 --- 把脏数据捋干净-CSDN博客

相关推荐
Xiu Yan38 分钟前
Python 数据分析:Pandas Series 零基础入门教程
python·jupyter·pycharm·numpy·pandas
I Am a robert girl39 分钟前
谷歌迈出RSI一大步:从Gemini模型迭代看AI工程化的新风向
人工智能·大模型·gemini·ai工程化·上下文工程·rsi·工具链集成
leoZ23141 分钟前
第 16 篇 转型路线图与求职实战
人工智能·大模型·agent
雪隐42 分钟前
16GB 显卡跑 Qwen3.8-27B,只要 7 GB:三进制模型 Bonsai 2 部署手记与双格式实测
人工智能·后端
心易行者42 分钟前
Python在线运行+SQLite数据库实战:0成本搭个人数据后台,5个场景直接套用
前端·网络·人工智能·python
蒲公英eric1 小时前
数学建模全流程:从一道题到一篇论文
人工智能·数学建模·数学建模竞赛·论文写作·建模流程
AI_AGENT_DEV_AI1 小时前
AI 智能体的开发流程
人工智能
俊哥V1 小时前
每日 AI 研究简报 · 2026-09-20
人工智能·ai
zhiyouTech1 小时前
GEO实战:把生成式引擎优化当成检索工程来做(含五断点诊断与50题Benchmark)
前端·人工智能