Skip to content

欢迎来到 第五阶段:工程化与底层(专家篇)

写出代码能跑是新手(Junior)的标准;写出优雅、可维护、不仅能跑还能跑得稳的代码,是资深工程师(Senior)的标准。

对于你(Node.js 背景),这一章相当于从“写 JS 脚本”进阶到“构建 TypeScript 大型架构”。


1. 面向对象编程 (OOP):架构的基石

Python 是多范式语言(既能写脚本,也能写类)。很多从 Java 转过来的人喜欢万物皆类,从 JS 转过来的人喜欢万物皆函数

什么时候该用类 (class),什么时候用函数 (def)?

黄金法则:

  • 如果你只需要行为(输入 -> 处理 -> 输出),用 函数

  • 如果你需要同时管理状态(Data)和行为(Methods),用

场景 A:发送邮件 (适合函数)

不需要记住之前的状态,发完就走。

Python

def send_email(to: str, content: str):
    # 连接 SMTP... 发送... 关闭
    pass

场景 B:AI 对话客户端 (适合类)

需要记住 api_key,需要记住 history (聊天记录上下文)。

Python

class AIChatBot:
    def __init__(self, api_key: str, model: str = "deepseek-chat"):
        """构造函数:初始化状态"""
        self.client = OpenAI(api_key=api_key) # 状态 1: 连接客户端
        self.model = model                    # 状态 2: 模型配置
        self.history = []                     # 状态 3: 记忆

    def chat(self, user_input: str) -> str:
        """方法:使用状态并更新状态"""
        self.history.append({"role": "user", "content": user_input})
        
        response = self.client.chat.completions.create(
            model=self.model,
            messages=self.history
        )
        
        reply = response.choices[0].message.content
        self.history.append({"role": "assistant", "content": reply})
        return reply

# 使用
bot = AIChatBot("sk-...")
print(bot.chat("你好")) # 它记得之前的配置
print(bot.chat("我刚才说什么了?")) # 它记得之前的历史

2. 高级特性:Python 的“黑魔法”

掌握这三个特性,你的代码会瞬间变得“Pythonic”(地道)。

A. 装饰器 (@decorator)

本质:高阶函数(Higher-Order Function)。在不修改原函数代码的情况下,给函数增加额外的功能(如日志、计时、鉴权、重试)。

Node.js 类比:类似于 Express 的 Middleware,或者 AOP (面向切面编程)。

实战:写一个“自动重试”装饰器 (AI 调用必备)

Python

import time
from functools import wraps

def retry(max_retries=3, delay=1):
    def decorator(func):
        @wraps(func) # 保持原函数的元数据 (name, docstring)
        def wrapper(*args, **kwargs):
            for i in range(max_retries):
                try:
                    return func(*args, **kwargs) # 尝试执行原函数
                except Exception as e:
                    print(f"❌ 第 {i+1} 次尝试失败: {e},{delay}秒后重试...")
                    time.sleep(delay)
            raise Exception("🔥 重试多次失败")
        return wrapper
    return decorator

# 使用装饰器:这就把重试逻辑注入到了 call_ai_api 中
@retry(max_retries=3, delay=2)
def call_ai_api():
    import random
    if random.random() < 0.7: # 模拟 70% 概率失败
        raise ValueError("网络波动")
    return "✅ 成功获取数据"

# 调用
print(call_ai_api())

B. 生成器 (yield)

本质:惰性求值 (Lazy Evaluation)。函数执行到 yield 会暂停并返回一个值,下次调用 next() 从暂停处继续。

优势极度省内存

实战:读取 10GB 的日志文件

如果用 f.readlines(),内存直接爆炸。用 yield,内存占用几乎为零。

Python

def read_large_file(file_path):
    with open(file_path, 'r') as f:
        for line in f:
            yield line.strip() # 每次只吐出一行,不把整个文件加载到内存

# 使用
log_gen = read_large_file("huge_log.txt")
for line in log_gen:
    if "ERROR" in line:
        print(f"找到错误: {line}")

C. 上下文管理器 (with)

本质:自动管理资源(打开/关闭)。

原理:实现了 __enter____exit__ 方法。

实战:自定义一个计时器

Python

import time

class Timer:
    def __enter__(self):
        self.start = time.time()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.end = time.time()
        print(f"⏱️ 耗时: {self.end - self.start:.2f} 秒")

# 使用
with Timer():
    # 这里放任何你想计时的代码
    time.sleep(1.5)
    print("任务完成")
# 退出缩进时,自动打印耗时

3. 代码质量:像专家一样写代码

A. 类型注解 (Type Hints)

Python 3.5+ 引入。虽然 Python 运行时不强制类型,但在大型项目中,它是文档,也是救命稻草

Python

from typing import List, Dict, Optional

# 不好的写法
def process_data(data):
    return data['items']

# 好的写法 (IDE 会有智能提示,配合 mypy 工具可以静态检查)
def process_data(data: Dict[str, List[int]]) -> List[int]:
    """
    处理数据
    :param data: 包含 'items' 键的字典,值为整数列表
    """
    return data.get('items', [])

B. 单元测试 (pytest)

丢掉 Python 自带的 unittest 吧,pytest 才是业界标准。它不需要写类,直接写 assert

实战:测试上面的重试函数

  1. 安装:pip install pytest

  2. 新建 test_app.py

Python

import pytest
from your_module import AIChatBot # 假设你把代码存成了文件

def test_chatbot_initialization():
    bot = AIChatBot(api_key="sk-test")
    assert bot.model == "deepseek-chat"
    assert len(bot.history) == 0

def test_chat_flow():
    # 这里通常会 Mock 掉 OpenAI 的调用,防止真的扣费
    # 但为了演示简单,我们只测逻辑
    pass
  1. 运行:在终端输入 pytest

4. 部署进阶:Docker 生产级最佳实践

在第四阶段我们讲了基础 Docker。这里讲优化

目标:减小镜像体积,加快构建速度。

使用多阶段构建 (Multi-stage Build)

Node.js 开发者很熟悉这个,Python 也一样。我们不需要把编译工具(gcc)带到生产环境。

Dockerfile.prod (生产级配置)

Dockerfile

# 第一阶段:构建依赖 (Builder)
FROM python:3.10-slim as builder

WORKDIR /app
COPY requirements.txt .

# --user 安装到用户目录,方便后续复制
# --no-warn-script-location 忽略路径警告
RUN pip install --user --no-cache-dir -r requirements.txt

# 第二阶段:运行环境 (Runner) - 纯净的镜像
FROM python:3.10-slim

WORKDIR /app

# 从 builder 阶段只复制安装好的库,不复制 pip 等工具
COPY --from=builder /root/.local /root/.local
COPY . .

# 确保 Python 能找到刚刚复制的库
ENV PATH=/root/.local/bin:$PATH

# 生产环境通常用 gunicorn 或 uvicorn 启动
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

第五阶段实战作业:重构 AI 内容工厂

你现在的 main.py 可能所有的逻辑都写在一起。请按照工程化标准重构它:

  1. OOP 重构:创建一个 ContentGenerator 类,把 generate_articlegenerate_image 方法封装进去。

  2. 增加装饰器:给所有 AI 调用的方法加上 @retry@log_execution_time(记录耗时)。

  3. 类型注解:给所有函数参数加上 Type Hints。

  4. 编写测试:写一个 test_generator.py,测试 Prompt 拼接逻辑是否正确。

完成了这一步,你写的就不再是“脚本”,而是**“企业级软件”**了。

需要我帮你演示如何把之前的代码重构成这个 OOP 版本吗?

坚持是一种品格