Skip to content

Python 系统学习文档 ​

适合人群:已经掌握 JavaScript/TypeScript,准备学习 Python 后端、AI 应用开发、数据处理、LangChain/LangGraph、FastAPI 或自动化脚本的学习者。

学习目标:从 Python 基础语法入门,逐步掌握函数、模块、面向对象、类型标注、虚拟环境、包管理、异常、文件处理、异步、测试、FastAPI、数据处理和 AI 工程实践。

核对时间:2026-09-01。Python 官方当前稳定文档为 Python 3.14.7,Python 3.15 仍处于预发布文档阶段。学习和项目开发应优先使用稳定版本。

官方资料:


目录 ​

第一篇:Python 基础 ​

  1. Python 是什么
  2. 安装与运行
  3. 基本语法
  4. 数据类型
  5. 条件和循环
  6. 函数

第二篇:核心语言能力 ​

  1. list、tuple、dict、set
  2. 字符串处理
  3. 解包、推导式和切片
  4. 异常处理
  5. 模块和包
  6. 面向对象
  7. dataclass 和 enum

第三篇:工程化基础 ​

  1. 虚拟环境
  2. pip、requirements 和 pyproject
  3. 类型标注
  4. 文件和路径
  5. JSON、时间和日志
  6. 测试
  7. 代码风格和格式化

第四篇:后端与 AI 工程 ​

  1. 同步和异步
  2. FastAPI 基础
  3. Pydantic
  4. HTTP 请求
  5. 数据处理
  6. Python AI 生态
  7. LangChain/LangGraph 项目实践

第五篇:进阶 ​

  1. 迭代器和生成器
  2. 装饰器
  3. 上下文管理器
  4. 并发和多进程
  5. 性能优化
  6. 常见误区和学习路线
  7. 核心知识点深度补全

第一篇:Python 基础 ​

1. Python 是什么 ​

Python 是一门简洁、动态类型、解释型语言,广泛用于:

  • AI 应用开发
  • 数据分析
  • 自动化脚本
  • Web 后端
  • 爬虫
  • 科学计算
  • 运维工具

对前端开发者来说,Python 最大价值在 AI 方向:

  • LangChain、LangGraph 生态成熟。
  • 数据处理库丰富。
  • 模型、向量库、Embedding、RAG 示例大多优先支持 Python。
  • FastAPI 适合快速搭建 AI 服务。

2. 安装与运行 ​

查看版本:

bash
python --version

运行文件:

bash
python main.py

交互模式:

bash
python

第一个程序:

python
print("Hello Python")

注意:Windows 上可能需要使用 py 或 python3,具体看本机安装方式。

3. 基本语法 ​

Python 使用缩进表示代码块。

python
age = 18

if age >= 18:
    print("adult")
else:
    print("minor")

和 JavaScript 不同:

  • 不用分号。
  • 不用花括号。
  • 缩进有语义。
  • 变量无需声明类型。
  • None 类似 JS 中的 null。

注释:

python
# 单行注释

4. 数据类型 ​

常见类型:

python
name = "Alice"          # str
age = 18                # int
price = 19.99           # float
active = True           # bool
empty = None            # NoneType

容器:

python
names = ["Alice", "Bob"]           # list
point = (10, 20)                   # tuple
user = {"name": "Alice"}           # dict
tags = {"ai", "python"}            # set

Python 是动态类型,但不是无类型。每个值都有明确类型,只是变量名不固定绑定某个类型。

5. 条件和循环 ​

if:

python
if score >= 90:
    level = "A"
elif score >= 60:
    level = "B"
else:
    level = "C"

for:

python
for name in names:
    print(name)

while:

python
while count < 10:
    count += 1

遍历索引和值:

python
for index, name in enumerate(names):
    print(index, name)

6. 函数 ​

定义函数:

python
def add(a, b):
    return a + b

带类型标注:

python
def add(a: int, b: int) -> int:
    return a + b

默认参数:

python
def greet(name: str = "Guest") -> str:
    return f"Hello {name}"

关键字参数:

python
greet(name="Alice")

注意:可变默认参数是常见坑。

不要这样:

python
def append_item(item, items=[]):
    items.append(item)
    return items

推荐:

python
def append_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

第二篇:核心语言能力 ​

7. list、tuple、dict、set ​

list:

python
items = [1, 2, 3]
items.append(4)

tuple:

python
point = (10, 20)

dict:

python
user = {"id": 1, "name": "Alice"}
print(user["name"])

安全读取:

python
name = user.get("name", "Unknown")

set:

python
tags = {"python", "ai"}
tags.add("rag")

选择:

  • 有序列表:list。
  • 不可变组合:tuple。
  • 键值映射:dict。
  • 去重集合:set。

8. 字符串处理 ​

f-string:

python
name = "Alice"
message = f"Hello {name}"

常用:

python
text.strip()
text.lower()
text.upper()
text.split(",")
",".join(items)
text.replace("old", "new")

多行字符串:

python
prompt = """
你是一个 AI 助手。
请根据资料回答问题。
"""

Prompt 编写中,多行字符串非常常用。

9. 解包、推导式和切片 ​

解包:

python
a, b = (1, 2)

列表推导式:

python
squares = [x * x for x in numbers]

过滤:

python
active_users = [u for u in users if u["active"]]

切片:

python
items[0:10]
items[:10]
items[-1]

这些语法能让 Python 代码非常简洁,但不要为了炫技写得难读。

10. 异常处理 ​

python
try:
    result = service.run()
except ValueError as exc:
    print(f"参数错误: {exc}")
except Exception as exc:
    print(f"未知错误: {exc}")
finally:
    cleanup()

主动抛出:

python
raise ValueError("参数不能为空")

建议:

  • 不要吞掉异常。
  • 日志中保留错误上下文。
  • API 层把异常转换成清晰响应。
  • AI 工具调用中要把错误结构化返回。

11. 模块和包 ​

模块就是 .py 文件。

python
# math_utils.py
def add(a, b):
    return a + b

导入:

python
from math_utils import add

包是包含多个模块的目录,通常有:

text
app/
├── __init__.py
├── services.py
└── models.py

现代 Python 中 __init__.py 不是所有情况都必须,但保留它通常能让包结构更明确。

12. 面向对象 ​

python
class User:
    def __init__(self, name: str):
        self.name = name

    def greet(self) -> str:
        return f"Hello {self.name}"

使用:

python
user = User("Alice")
print(user.greet())

Python 的面向对象比 Java 更灵活,但大型项目仍然需要清晰边界。

AI 工程中常见类:

  • ModelClient
  • VectorStoreService
  • DocumentIngestor
  • AgentRunner
  • EvaluationService

13. dataclass 和 enum ​

dataclass:

python
from dataclasses import dataclass

@dataclass
class User:
    id: int
    name: str

enum:

python
from enum import Enum

class OrderStatus(str, Enum):
    pending = "pending"
    paid = "paid"
    cancelled = "cancelled"

在 API 和结构化输出中,枚举能减少字符串拼写错误。


第三篇:工程化基础 ​

14. 虚拟环境 ​

虚拟环境用于隔离项目依赖。

创建:

bash
python -m venv .venv

激活 Windows:

bash
.venv\Scripts\activate

激活 macOS/Linux:

bash
source .venv/bin/activate

为什么需要虚拟环境:

  • 不污染全局 Python。
  • 不同项目可以使用不同依赖版本。
  • 方便部署和复现。

15. pip、requirements 和 pyproject ​

安装依赖:

bash
pip install fastapi uvicorn

导出:

bash
pip freeze > requirements.txt

安装:

bash
pip install -r requirements.txt

现代项目越来越多使用 pyproject.toml 统一描述项目元数据、依赖和工具配置。

常见工具:

  • pip
  • uv
  • poetry
  • hatch
  • pdm

入门阶段先掌握 venv + pip,工程阶段再学习 uv 或 poetry。

16. 类型标注 ​

python
def greet(name: str) -> str:
    return f"Hello {name}"

集合类型:

python
def total(values: list[int]) -> int:
    return sum(values)

可选类型:

python
def find_user(id: int) -> User | None:
    ...

类型标注不会自动阻止运行时错误,但能提升 IDE 提示、静态检查和团队协作质量。

常见工具:

  • mypy
  • pyright
  • ruff

17. 文件和路径 ​

推荐使用 pathlib。

python
from pathlib import Path

path = Path("data") / "input.txt"
content = path.read_text(encoding="utf-8")

写文件:

python
path.write_text("hello", encoding="utf-8")

读取目录:

python
for file in Path("docs").glob("*.md"):
    print(file)

RAG 文档导入、日志处理、批处理脚本都会大量用到文件操作。

18. JSON、时间和日志 ​

JSON:

python
import json

data = json.loads(text)
text = json.dumps(data, ensure_ascii=False)

时间:

python
from datetime import datetime, timezone

now = datetime.now(timezone.utc)

日志:

python
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
logger.info("started")

生产项目不要只用 print,要使用 logging。

19. 测试 ​

pytest:

python
def add(a: int, b: int) -> int:
    return a + b

def test_add():
    assert add(1, 2) == 3

运行:

bash
pytest

AI 应用测试:

  • 普通函数用单元测试。
  • Prompt 输出用评估集。
  • RAG 检索用固定问题集。
  • Agent 工具用 mock。

20. 代码风格和格式化 ​

常见工具:

  • ruff:lint 和格式化。
  • black:格式化。
  • isort:导入排序。
  • mypy/pyright:类型检查。
  • pytest:测试。

推荐命令:

bash
ruff check .
ruff format .
pytest

Python 工程质量来自:

  • 明确项目结构。
  • 类型标注。
  • 自动格式化。
  • 单元测试。
  • 日志和配置管理。

第四篇:后端与 AI 工程 ​

21. 同步和异步 ​

同步:

python
def fetch_data():
    return requests.get(url).json()

异步:

python
async def fetch_data():
    async with httpx.AsyncClient() as client:
        response = await client.get(url)
        return response.json()

异步适合:

  • 网络 I/O
  • 数据库 I/O
  • 多个模型/API 并发请求

不要为了异步而异步。CPU 密集任务不一定适合 asyncio。

22. FastAPI 基础 ​

安装:

bash
pip install fastapi uvicorn

示例:

python
from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
def health():
    return {"status": "ok"}

运行:

bash
uvicorn main:app --reload

FastAPI 优势:

  • 类型标注驱动。
  • 自动生成 OpenAPI。
  • 与 Pydantic 集成。
  • 适合 AI 服务 API。

23. Pydantic ​

Pydantic 用于数据校验和序列化。

python
from pydantic import BaseModel

class ChatRequest(BaseModel):
    message: str
    session_id: str

FastAPI 中:

python
@app.post("/chat")
def chat(request: ChatRequest):
    return {"reply": request.message}

Pydantic 对 AI 工程很重要:

  • 校验 API 输入。
  • 定义结构化输出。
  • 定义 Agent 状态。
  • 定义工具参数。

24. HTTP 请求 ​

同步:

python
import requests

response = requests.get("https://api.example.com")
data = response.json()

异步:

python
import httpx

async with httpx.AsyncClient() as client:
    response = await client.get("https://api.example.com")

调用模型 API、业务 API、检索服务都会用到 HTTP。

要处理:

  • timeout
  • retry
  • status code
  • error response
  • rate limit

25. 数据处理 ​

常用库:

  • pandas
  • numpy
  • pydantic
  • pathlib
  • json
  • csv

CSV:

python
import csv

with open("data.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    rows = list(reader)

pandas:

python
import pandas as pd

df = pd.read_csv("data.csv")
summary = df.groupby("category")["amount"].sum()

AI 项目中常见数据处理:

  • 文档清洗
  • 表格转文本
  • 日志分析
  • 评估结果统计

26. Python AI 生态 ​

常见方向:

  • LLM 应用:LangChain、LangGraph、LlamaIndex
  • API 服务:FastAPI
  • 数据处理:pandas、numpy
  • 向量库:Chroma、FAISS、Milvus、Qdrant
  • 模型调用:各模型 SDK
  • 评估:RAGAS、自定义 eval、LangSmith
  • 部署:Docker、Uvicorn、Gunicorn

前端 AI 全栈不一定要训练模型,但要会:

  • 调模型
  • 做 RAG
  • 写工具
  • 做 Agent 状态
  • 暴露 API
  • 接前端流式 UI

27. LangChain/LangGraph 项目实践 ​

结构:

text
ai-service/
├── app/
│   ├── api/
│   ├── agents/
│   ├── graphs/
│   ├── retrievers/
│   ├── tools/
│   ├── schemas/
│   └── services/
├── tests/
└── pyproject.toml

推荐学习项目:

text
文档问答服务
- FastAPI 提供 /chat
- LangChain 做 RAG
- LangGraph 做审批型长任务
- PostgreSQL/pgvector 保存向量
- 前端 Nuxt 展示流式回答和引用来源

第五篇:进阶 ​

28. 迭代器和生成器 ​

迭代器:

python
for item in items:
    ...

生成器:

python
def count_up_to(n):
    i = 0
    while i < n:
        yield i
        i += 1

生成器适合:

  • 大文件逐行处理。
  • 流式数据。
  • 避免一次性加载全部内容。

LLM streaming 也可以用生成器思想理解。

29. 装饰器 ​

装饰器用于包装函数。

python
def log_time(func):
    def wrapper(*args, **kwargs):
        print("start")
        result = func(*args, **kwargs)
        print("end")
        return result
    return wrapper

@log_time
def run():
    print("running")

常见用途:

  • 日志
  • 鉴权
  • 缓存
  • 重试
  • 路由注册

FastAPI 的 @app.get 就是装饰器。

30. 上下文管理器 ​

python
with open("a.txt", encoding="utf-8") as f:
    content = f.read()

with 会自动释放资源。

适合:

  • 文件
  • 数据库连接
  • 网络连接
  • 临时资源
  • trace/span

异步上下文:

python
async with httpx.AsyncClient() as client:
    ...

31. 并发和多进程 ​

Python 常见并发方式:

  • threading:线程。
  • multiprocessing:多进程。
  • asyncio:异步 I/O。
  • concurrent.futures:统一接口。

选择:

  • 网络 I/O:asyncio。
  • 简单并发任务:ThreadPoolExecutor。
  • CPU 密集:ProcessPoolExecutor 或专门计算框架。

AI 应用中多数瓶颈是网络 I/O,例如模型 API、向量库、外部服务,因此 asyncio 很常用。

32. 性能优化 ​

优先级:

  1. 找到瓶颈。
  2. 减少不必要 I/O。
  3. 缓存重复计算。
  4. 批量处理。
  5. 异步并发。
  6. 使用更合适的数据结构。
  7. 必要时使用原生扩展或专门系统。

不要一开始就微优化。AI 应用中更常见的问题是:

  • Prompt 太长。
  • 检索太慢。
  • 模型太贵。
  • 串行调用太多。
  • 没有缓存。

33. 常见误区和学习路线 ​

误区一:Python 简单,所以不需要工程化。

纠正:Python 写脚本容易,写长期维护的服务仍然需要结构、测试、类型和日志。

误区二:AI 开发等于训练模型。

纠正:大多数 AI 全栈岗位更需要模型调用、RAG、Agent、数据处理和产品落地。

误区三:动态类型就不用类型标注。

纠正:类型标注能显著提升大型 Python 项目可维护性。

学习路线:

  1. 基础语法和数据结构。
  2. 函数、模块、异常。
  3. 类型标注和 dataclass。
  4. venv、pip、pyproject。
  5. 文件、JSON、日志。
  6. pytest 和 ruff。
  7. FastAPI 和 Pydantic。
  8. asyncio 和 httpx。
  9. LangChain/LangGraph。
  10. RAG、向量库和评估。

34. 核心知识点深度补全 ​

本章补全 Python 学习中最容易被轻描淡写的部分:数据结构、迭代协议、生成器、装饰器、上下文管理器、类型标注、GIL、线程/进程/协程与 asyncio。目标是让你不仅会写脚本,还能写可维护的 AI 服务和后端工程代码。

34.1 list、tuple、dict、set 的选择 ​

类型是否可变是否有序典型用途
list可变有序动态列表、队列、小规模数据处理
tuple不可变有序固定结构、函数多返回值、不可变记录
dict可变保持插入顺序key-value 映射、JSON 对象、配置
set可变不保证业务顺序去重、成员判断、集合运算
frozenset不可变不保证业务顺序可作为 dict key 的集合

list 适合按顺序存储:

python
users = ["Alice", "Bob"]
users.append("Cindy")
print(users[0])

tuple 适合表达固定结构:

python
point = (10, 20)
x, y = point

dict 是 Python 工程中最常见的数据结构:

python
user = {
    "id": 1,
    "name": "Alice",
    "roles": ["admin"],
}

print(user.get("name"))

set 适合成员判断:

python
allowed_roles = {"admin", "editor"}

if "admin" in allowed_roles:
    print("ok")

34.2 可变对象与引用陷阱 ​

Python 变量保存的是对象引用,不是对象本身。

python
a = [1, 2]
b = a
b.append(3)
print(a)  # [1, 2, 3]

函数默认参数陷阱:

python
def add_item(item, items=[]):
    items.append(item)
    return items

print(add_item("a"))  # ["a"]
print(add_item("b"))  # ["a", "b"],不是你想要的

正确写法:

python
def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

浅拷贝与深拷贝:

python
import copy

users = [{"name": "Alice"}]

shallow = users.copy()
deep = copy.deepcopy(users)

shallow[0]["name"] = "Bob"
print(users[0]["name"])  # Bob

deep[0]["name"] = "Cindy"
print(users[0]["name"])  # Bob

34.3 dict 的常见工程写法 ​

合并字典:

python
base = {"timeout": 3, "retries": 2}
override = {"timeout": 10}

config = base | override
print(config)  # {"timeout": 10, "retries": 2}

安全读取嵌套字段:

python
payload = {"user": {"profile": {"name": "Alice"}}}
name = payload.get("user", {}).get("profile", {}).get("name")

统计频率:

python
from collections import Counter

words = ["vue", "python", "vue", "ai"]
counter = Counter(words)
print(counter.most_common(2))

按 key 分组:

python
from collections import defaultdict

orders = [
    {"user_id": 1, "amount": 100},
    {"user_id": 1, "amount": 50},
    {"user_id": 2, "amount": 80},
]

groups = defaultdict(list)
for order in orders:
    groups[order["user_id"]].append(order)

34.4 迭代协议 ​

可迭代对象实现 __iter__,迭代器实现 __iter__ 和 __next__。

python
items = [1, 2, 3]
iterator = iter(items)

print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3

for 循环本质上就是不断调用 iter() 和 next(),直到捕获 StopIteration。

自定义迭代器:

python
class Countdown:
    def __init__(self, start: int):
        self.current = start

    def __iter__(self):
        return self

    def __next__(self):
        if self.current <= 0:
            raise StopIteration
        value = self.current
        self.current -= 1
        return value

for number in Countdown(3):
    print(number)

更推荐用生成器简化:

python
def countdown(start: int):
    while start > 0:
        yield start
        start -= 1

34.5 生成器与惰性计算 ​

生成器函数遇到 yield 会暂停,把值交给调用方;下次继续从暂停处执行。

python
def read_lines(path: str):
    with open(path, "r", encoding="utf-8") as file:
        for line in file:
            yield line.strip()

优点:

  • 不需要一次性把所有数据加载到内存。
  • 适合处理大文件、流式响应、模型输出流。
  • 可以和管道式处理组合。

生成器表达式:

python
squares = (x * x for x in range(1_000_000))
print(next(squares))

列表推导式会立即创建完整列表:

python
squares = [x * x for x in range(1_000_000)]

AI streaming 场景:

python
def stream_tokens(text: str):
    for token in text.split():
        yield token

for token in stream_tokens("hello streaming world"):
    print(token)

34.6 装饰器:函数包装与元数据保留 ​

装饰器本质是“接收函数,返回新函数”的高阶函数。

python
def log_call(func):
    def wrapper(*args, **kwargs):
        print(f"calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@log_call
def add(a, b):
    return a + b

等价于:

python
add = log_call(add)

生产代码应使用 functools.wraps 保留原函数元数据:

python
from functools import wraps

def log_call(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

带参数装饰器:

python
from functools import wraps
from time import perf_counter

def timer(name: str):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start = perf_counter()
            try:
                return func(*args, **kwargs)
            finally:
                cost = perf_counter() - start
                print(f"{name} cost {cost:.3f}s")
        return wrapper
    return decorator

@timer("load_user")
def load_user(user_id: int):
    return {"id": user_id}

常见用途:

  • 日志。
  • 权限校验。
  • 重试。
  • 缓存。
  • 计时。
  • Web 框架路由注册,例如 FastAPI 的 @app.get。

34.7 上下文管理器 ​

上下文管理器用于管理资源的进入和退出,典型语法是 with。

python
with open("data.txt", "r", encoding="utf-8") as file:
    content = file.read()

无论中间是否抛异常,文件都会被关闭。

自定义上下文管理器:

python
class ManagedResource:
    def __enter__(self):
        print("open")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("close")
        return False  # 不吞异常

with ManagedResource() as resource:
    print("use")

使用 contextlib:

python
from contextlib import contextmanager

@contextmanager
def managed_resource():
    print("open")
    try:
        yield "resource"
    finally:
        print("close")

with managed_resource() as resource:
    print(resource)

常见用途:

  • 文件。
  • 数据库连接和事务。
  • 临时目录。
  • 锁。
  • 测试中的 mock patch。

34.8 类型标注不是运行时类型检查 ​

类型标注主要服务于 IDE、静态检查、协作维护,不会自动阻止运行时传错类型。

python
def add(a: int, b: int) -> int:
    return a + b

print(add("1", "2"))  # 运行时仍可执行,结果是 "12"

常用写法:

python
from typing import TypedDict, Literal, Protocol

type UserId = int

class User(TypedDict):
    id: UserId
    name: str
    role: Literal["admin", "editor", "viewer"]

class Sender(Protocol):
    def send(self, message: str) -> None:
        ...

Protocol 适合表达结构化接口:

python
def notify(sender: Sender, message: str) -> None:
    sender.send(message)

工程建议:

  • 函数边界加类型。
  • 复杂 dict 用 TypedDict 或 Pydantic model。
  • 公共模块开启 mypy/pyright 检查。
  • 不要为了类型体操牺牲可读性。

34.9 GIL:全局解释器锁 ​

CPython 中有 GIL(Global Interpreter Lock),同一时刻通常只有一个线程执行 Python 字节码。它不代表 Python 不能并发,而是影响 CPU 密集型多线程的并行能力。

适合线程的场景:

  • 网络请求。
  • 文件 I/O。
  • 数据库调用。
  • 等待外部服务。

不适合用普通线程加速的场景:

  • 大量纯 Python CPU 计算。
  • 图片/音频/文本大规模计算。
  • 大型循环中的数学运算。

选择:

任务类型推荐
I/O 密集,代码简单ThreadPoolExecutor
I/O 密集,连接数多asyncio + async HTTP/DB 客户端
CPU 密集ProcessPoolExecutor、原生扩展、专门计算框架
Web API 服务FastAPI/Starlette 等异步框架

线程池示例:

python
from concurrent.futures import ThreadPoolExecutor

def fetch(url: str) -> str:
    return f"content of {url}"

urls = ["https://example.com/a", "https://example.com/b"]

with ThreadPoolExecutor(max_workers=8) as executor:
    results = list(executor.map(fetch, urls))

进程池示例:

python
from concurrent.futures import ProcessPoolExecutor

def compute(n: int) -> int:
    return sum(i * i for i in range(n))

with ProcessPoolExecutor() as executor:
    results = list(executor.map(compute, [1_000_000, 2_000_000]))

34.10 asyncio 的执行模型 ​

asyncio 是单线程事件循环模型,适合高并发 I/O。关键概念:

概念含义
coroutine协程对象,由 async 函数调用产生
event loop事件循环,调度协程和 I/O
task被事件循环调度的协程包装
await暂停当前协程,把控制权还给事件循环
gather并发等待多个 awaitable

基础示例:

python
import asyncio

async def fetch_user(user_id: int) -> dict:
    await asyncio.sleep(1)
    return {"id": user_id}

async def main():
    user = await fetch_user(1)
    print(user)

asyncio.run(main())

并发执行:

python
async def main():
    users = await asyncio.gather(
        fetch_user(1),
        fetch_user(2),
        fetch_user(3),
    )
    print(users)

串行陷阱:

python
async def slow():
    a = await fetch_user(1)
    b = await fetch_user(2)
    return a, b

并发写法:

python
async def fast():
    task_a = asyncio.create_task(fetch_user(1))
    task_b = asyncio.create_task(fetch_user(2))
    return await task_a, await task_b

34.11 asyncio 取消、超时与限流 ​

超时:

python
async def main():
    try:
        result = await asyncio.wait_for(fetch_user(1), timeout=0.5)
    except asyncio.TimeoutError:
        result = None
    print(result)

限流:

python
import asyncio

semaphore = asyncio.Semaphore(5)

async def limited_fetch(user_id: int):
    async with semaphore:
        return await fetch_user(user_id)

取消:

python
async def main():
    task = asyncio.create_task(fetch_user(1))
    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print("cancelled")

工程注意:

  • async 函数里不要调用长时间阻塞的同步函数。
  • 选择支持 async 的 HTTP/数据库客户端,例如 httpx async client、asyncpg 等。
  • 每个外部服务都要有限流和超时。
  • 被取消的协程要正确释放资源。

34.12 FastAPI 与 asyncio 的关系 ​

FastAPI 支持同步和异步路由:

python
@app.get("/sync")
def sync_api():
    return {"ok": True}

@app.get("/async")
async def async_api():
    return {"ok": True}

如果路由内部主要是异步 I/O,使用 async def:

python
@app.get("/users/{user_id}")
async def get_user(user_id: int):
    data = await user_client.fetch_user(user_id)
    return data

如果内部调用的是阻塞 SDK,不要简单套一层 async:

python
@app.get("/bad")
async def bad():
    result = blocking_sdk.call()  # 会阻塞事件循环
    return result

可以:

  • 使用 SDK 的异步版本。
  • 把阻塞调用放到线程池。
  • 在服务架构上隔离慢任务。

34.13 dataclass、Pydantic 与业务模型 ​

dataclass 适合纯 Python 内部数据结构:

python
from dataclasses import dataclass

@dataclass(frozen=True)
class User:
    id: int
    name: str

Pydantic 适合 API 入参、配置、外部数据校验:

python
from pydantic import BaseModel, Field

class CreateUserRequest(BaseModel):
    name: str = Field(min_length=1, max_length=50)
    age: int = Field(ge=0, le=150)

选择:

  • 内部计算模型:dataclass。
  • API 边界和外部输入:Pydantic。
  • 简单临时结构:dict。
  • 复杂业务实体:普通 class 或领域模型。

34.14 Python 工程代码质量清单 ​

  1. 函数是否有明确输入输出。
  2. 公共函数是否有类型标注。
  3. 可变默认参数是否避免。
  4. 外部 I/O 是否有超时。
  5. 并发请求是否有限流。
  6. 异常是否带上下文日志。
  7. dict 结构是否过深,是否需要模型。
  8. 大文件是否流式处理。
  9. 测试是否覆盖成功、失败、边界。
  10. 依赖是否锁定版本并隔离虚拟环境。

35. 语言机制深度补全 ​

本章补全 Python 里「知道怎么用但不知其所以然」的语言机制:作用域与闭包、参数传递语义、面向对象进阶、字符串与字节编码、导入机制。理解这些能让 AI 服务和后端代码更可靠,也能快速定位那些「玄学 bug」。

35.1 作用域:LEGB 规则 ​

Python 查找名字时按 LEGB 顺序:

text
L(Local)      函数内部
E(Enclosing)  外层函数(闭包)
G(Global)     模块全局
B(Builtin)    内建名称(print、len 等)
python
x = "global"

def outer():
    x = "enclosing"
    def inner():
        print(x)   # 依次查 inner -> outer -> global -> builtin
    inner()

outer()  # enclosing

在函数内「读」外层变量没问题,但「赋值」会默认创建局部变量:

python
count = 0

def increment():
    count = count + 1   # UnboundLocalError

原因:函数体内对 count 赋值,Python 把它当作局部变量,但右侧读取时局部变量还没定义。

需要修改外层变量时显式声明:

python
count = 0

def increment():
    global count       # 声明修改模块级变量
    count += 1

def outer():
    n = 0
    def inner():
        nonlocal n     # 声明修改外层函数的变量
        n += 1
    inner()
    return n

工程建议:global 尽量少用(可维护性差),闭包中用 nonlocal 时也要克制 —— 大量可变闭包状态会让逻辑难追踪。

35.2 闭包与延迟绑定 ​

闭包是「捕获了外层作用域变量的函数」。经典陷阱是循环中的延迟绑定:

python
callbacks = []
for i in range(3):
    callbacks.append(lambda: i)

print([f() for f in callbacks])  # [2, 2, 2],不是 [0, 1, 2]

原因:lambda 捕获的是变量 i 本身,循环结束后 i == 2,三个函数看到的都是 2。

解决:用默认参数在定义时「快照」当前值:

python
callbacks = [lambda i=i: i for i in range(3)]
print([f() for f in callbacks])  # [0, 1, 2]

这是「默认参数在函数定义时求值」这一特性的刻意运用(默认参数坑见第 6 章)。工程上更推荐避免在循环里制造裸 lambda,改用偏函数或明确函数。

35.3 *args、**kwargs 与参数传递 ​

*args 收集位置参数为 tuple,**kwargs 收集关键字参数为 dict:

python
def build_request(method, *args, **kwargs):
    print(method)      # "POST"
    print(args)        # ("/api/users",)
    print(kwargs)      # {"timeout": 3, "retries": 2}

build_request("POST", "/api/users", timeout=3, retries=2)

拆包(调用侧):* 展开序列,** 展开映射:

python
params = {"timeout": 3, "retries": 2}
build_request("POST", "/api/users", **params)

values = [1, 2, 3]
total(*values)   # 等价 total(1, 2, 3)

⚠️ 一个关键语义:Python 的「参数传递」既不是值传递也不是引用传递,而是「按对象引用传递」。函数内对参数重新赋值不会影响调用方,但修改可变对象的内容会影响:

python
def append(item, items):
    items.append(item)   # 修改调用方传入的 list

def reassign(items):
    items = []           # 只改了局部名字,调用方不受影响

理解这一点能避免大量「为什么 list 传进去被改了」的困惑。

35.4 面向对象进阶:魔术方法、property、super 与 MRO ​

魔术方法(dunder methods)让自定义类融入 Python 协议:

python
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):          # 调试用的可读表示
        return f"Vector({self.x}, {self.y})"

    def __eq__(self, other):     # 支持 ==
        return (self.x, self.y) == (other.x, other.y)

    def __add__(self, other):    # 支持 +
        return Vector(self.x + other.x, self.y + other.y)

property 把方法伪装成属性,用于受控访问:

python
class Account:
    def __init__(self, balance):
        self._balance = balance

    @property
    def balance(self):
        return self._balance

    @balance.setter
    def balance(self, value):
        if value < 0:
            raise ValueError("余额不能为负")
        self._balance = value

super() 用于调用父类方法,配合多继承时按 MRO(Method Resolution Order,方法解析顺序)查找:

python
class B: pass
class C: pass
class D(B, C): pass

print(D.__mro__)  # (D, B, C, object)

MRO 用 C3 线性化算法确定,super() 严格按 MRO 顺序找下一个实现,不是简单「找父类」。理解 MRO 能解释多继承下 super() 的实际调用路径,避免「明明调了父类却跳到了另一个类」的困惑。

35.5 类变量 vs 实例变量、slots ​

类变量属于类,所有实例共享;实例变量属于实例:

python
class Config:
    default_timeout = 3      # 类变量,所有实例共享

    def __init__(self, timeout=None):
        self.timeout = timeout or self.default_timeout   # 实例变量

⚠️ 通过实例给「看起来像类变量」的名字赋值,会创建实例变量,而不是修改类变量:

python
Config.default_timeout = 5      # 修改类变量
c = Config()
c.default_timeout = 10          # 创建实例变量,类变量仍是 5

__slots__ 限制实例只能有指定属性,节省内存(不再为每个实例创建 __dict__):

python
class Point:
    __slots__ = ("x", "y")

    def __init__(self, x, y):
        self.x = x
        self.y = y

要点:__slots__ 会去掉 __dict__,实例不能动态添加属性;大规模创建小对象(如数据处理中的记录)时能显著省内存,普通业务类不必刻意使用。

35.6 字符串与字节:str、bytes 与编码 ​

Python 3 严格区分「文本」str 和「字节」bytes:

python
text = "中文"                          # str,Unicode 码点序列
raw = text.encode("utf-8")             # bytes,UTF-8 编码后的字节
back = raw.decode("utf-8")             # str

print(type(raw))   # <class 'bytes'>
print(raw)         # b'\xe4\xb8\xad\xe6\x96\x87'

要点:

  • str 是无编码概念的「Unicode 字符串」,bytes 才是编码后的字节流。
  • 读写文件、网络传输都涉及「str ↔ bytes」转换,要显式指定编码,避免依赖平台默认编码。
  • Python 3.14 及以前,open() 的默认编码依赖 locale(PEP 686 计划在 Python 3.15 将 UTF-8 设为默认);跨平台代码应显式写 encoding="utf-8"。
  • 常见错误 UnicodeDecodeError / UnicodeEncodeError 基本都源于「用错编码解码/编码」。

AI 工程中处理文档、日志、API 响应时,「文本与字节的边界」是最常见的编码坑来源。

35.7 导入机制与模块缓存 ​

import 会执行模块代码一次,并把模块对象缓存到 sys.modules:

python
import sys

import math_utils
print(math_utils is sys.modules["math_utils"])  # True

要点:

  • 同一模块在同一进程内只会执行一次顶层代码,后续 import 直接取缓存。
  • 这解释了为什么「重复 import 不会重复执行模块级代码」,也解释了「改了文件但不重启进程,import 不会生效」(缓存)。
  • 模块级代码(如连接数据库、读配置)会随 import 执行,属于副作用,要注意放置位置。
  • from module import name 会执行整个模块,只是只把 name 绑定到当前命名空间。

包 vs 模块:包是含 __init__.py 的目录,import package.module 会先执行 package/__init__.py。现代 Python 中 __init__.py 可省略(命名空间包),但显式保留能让结构更清晰、避免命名空间包带来的路径歧义。


快速记忆清单 ​

  • Python 是 AI 工程生态最重要的语言之一。
  • 缩进是语法,不是格式偏好。
  • list、dict、set、tuple 是基础中的基础。
  • 虚拟环境必须掌握,避免依赖污染。
  • 类型标注不会改变运行时,但能提升工程质量。
  • FastAPI + Pydantic 是 AI 服务常见组合。
  • LangChain/LangGraph 学习离不开 Python 工程基础。
  • 前端 AI 全栈不一定训练模型,但必须会把模型能力做成稳定产品。

基于 VitePress 构建的个人学习文档知识库