python-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Python Patterns

Python开发模式

Python development principles and decision-making for 2025. Learn to THINK, not memorize patterns.

2025年Python开发原则与决策制定。 学会思考,而非死记模式。

⚠️ How to Use This Skill

⚠️ 如何使用本技能

This skill teaches decision-making principles, not fixed code to copy.
  • ASK user for framework preference when unclear
  • Choose async vs sync based on CONTEXT
  • Don't default to same framework every time

本技能传授决策原则,而非可供复制的固定代码。
  • 当用户需求不明确时,询问其框架偏好
  • 根据业务场景选择异步或同步方案
  • 不要每次都默认使用同一框架

1. Framework Selection (2025)

1. 2025年框架选择

Decision Tree

决策树

What are you building?
├── API-first / Microservices
│   └── FastAPI (async, modern, fast)
├── Full-stack web / CMS / Admin
│   └── Django (batteries-included)
├── Simple / Script / Learning
│   └── Flask (minimal, flexible)
├── AI/ML API serving
│   └── FastAPI (Pydantic, async, uvicorn)
└── Background workers
    └── Celery + any framework
你要构建什么类型的项目?
├── API优先 / 微服务
│   └── FastAPI(异步、现代化、高性能)
├── 全栈网站 / CMS / 后台管理系统
│   └── Django(开箱即用)
├── 简单脚本 / 学习项目
│   └── Flask(轻量、灵活)
├── AI/ML API部署
│   └── FastAPI(搭配Pydantic、异步、uvicorn)
└── 后台任务
    └── Celery + 任意框架

Comparison Principles

对比原则

FactorFastAPIDjangoFlask
Best forAPIs, microservicesFull-stack, CMSSimple, learning
AsyncNativeDjango 5.0+Via extensions
AdminManualBuilt-inVia extensions
ORMChoose your ownDjango ORMChoose your own
Learning curveLowMediumLow
考量因素FastAPIDjangoFlask
适用场景API、微服务全栈、CMS简单项目、学习
异步支持原生支持Django 5.0+支持通过扩展实现
后台管理界面需手动搭建内置通过扩展实现
ORM可自主选择Django ORM可自主选择
学习曲线中等

Selection Questions to Ask:

选择时需询问的问题:

  1. Is this API-only or full-stack?
  2. Need admin interface?
  3. Team familiar with async?
  4. Existing infrastructure?

  1. 是纯API项目还是全栈项目?
  2. 是否需要后台管理界面?
  3. 团队熟悉异步开发吗?
  4. 现有基础设施是什么?

2. Async vs Sync Decision

2. 异步与同步决策

When to Use Async

何时使用异步

async def is better when:
├── I/O-bound operations (database, HTTP, file)
├── Many concurrent connections
├── Real-time features
├── Microservices communication
└── FastAPI/Starlette/Django ASGI

def (sync) is better when:
├── CPU-bound operations
├── Simple scripts
├── Legacy codebase
├── Team unfamiliar with async
└── Blocking libraries (no async version)
优先使用async def的场景:
├── I/O密集型操作(数据库、HTTP请求、文件操作)
├── 高并发连接场景
├── 实时功能
├── 微服务间通信
├── FastAPI/Starlette/Django ASGI部署

优先使用def(同步)的场景:
├── CPU密集型操作
├── 简单脚本
├── 遗留代码库
├── 团队不熟悉异步开发
├── 使用无异步版本的阻塞库

The Golden Rule

黄金准则

I/O-bound → async (waiting for external)
CPU-bound → sync + multiprocessing (computing)

Don't:
├── Mix sync and async carelessly
├── Use sync libraries in async code
└── Force async for CPU work
I/O密集型 → 异步(等待外部资源)
CPU密集型 → 同步+多进程(计算任务)

禁止:
├── 随意混合异步与同步代码
├── 在异步代码中使用同步库
├── 强制为CPU密集型任务使用异步

Async Library Selection

异步库选择

NeedAsync Library
HTTP clienthttpx
PostgreSQLasyncpg
Redisaioredis / redis-py async
File I/Oaiofiles
Database ORMSQLAlchemy 2.0 async, Tortoise

需求异步库
HTTP客户端httpx
PostgreSQLasyncpg
Redisaioredis / redis-py async
文件I/Oaiofiles
数据库ORMSQLAlchemy 2.0 async, Tortoise

3. Type Hints Strategy

3. 类型提示策略

When to Type

何时使用类型提示

Always type:
├── Function parameters
├── Return types
├── Class attributes
├── Public APIs

Can skip:
├── Local variables (let inference work)
├── One-off scripts
├── Tests (usually)
必须添加类型提示的场景:
├── 函数参数
├── 返回值类型
├── 类属性
├── 公共API

可跳过的场景:
├── 局部变量(让类型推断自动处理)
├── 一次性脚本
├── 测试代码(通常情况下)

Common Type Patterns

常见类型模式

python
undefined
python
undefined

These are patterns, understand them:

这些是模式,理解其原理:

Optional → might be None

Optional → 可能为None

from typing import Optional def find_user(id: int) -> Optional[User]: ...
from typing import Optional def find_user(id: int) -> Optional[User]: ...

Union → one of multiple types

Union → 多种类型之一

def process(data: str | dict) -> None: ...
def process(data: str | dict) -> None: ...

Generic collections

泛型集合

def get_items() -> list[Item]: ... def get_mapping() -> dict[str, int]: ...
def get_items() -> list[Item]: ... def get_mapping() -> dict[str, int]: ...

Callable

Callable

from typing import Callable def apply(fn: Callable[[int], str]) -> str: ...
undefined
from typing import Callable def apply(fn: Callable[[int], str]) -> str: ...
undefined

Pydantic for Validation

使用Pydantic进行验证

When to use Pydantic:
├── API request/response models
├── Configuration/settings
├── Data validation
├── Serialization

Benefits:
├── Runtime validation
├── Auto-generated JSON schema
├── Works with FastAPI natively
└── Clear error messages

何时使用Pydantic:
├── API请求/响应模型
├── 配置/设置
├── 数据验证
├── 序列化

优势:
├── 运行时验证
├── 自动生成JSON Schema
├── 与FastAPI原生集成
├── 清晰的错误提示

4. Project Structure Principles

4. 项目结构原则

Structure Selection

结构选择

Small project / Script:
├── main.py
├── utils.py
└── requirements.txt

Medium API:
├── app/
│   ├── __init__.py
│   ├── main.py
│   ├── models/
│   ├── routes/
│   ├── services/
│   └── schemas/
├── tests/
└── pyproject.toml

Large application:
├── src/
│   └── myapp/
│       ├── core/
│       ├── api/
│       ├── services/
│       ├── models/
│       └── ...
├── tests/
└── pyproject.toml
小型项目 / 脚本:
├── main.py
├── utils.py
└── requirements.txt

中型API项目:
├── app/
│   ├── __init__.py
│   ├── main.py
│   ├── models/
│   ├── routes/
│   ├── services/
│   └── schemas/
├── tests/
└── pyproject.toml

大型应用:
├── src/
│   └── myapp/
│       ├── core/
│       ├── api/
│       ├── services/
│       ├── models/
│       └── ...
├── tests/
└── pyproject.toml

FastAPI Structure Principles

FastAPI结构原则

Organize by feature or layer:

By layer:
├── routes/ (API endpoints)
├── services/ (business logic)
├── models/ (database models)
├── schemas/ (Pydantic models)
└── dependencies/ (shared deps)

By feature:
├── users/
│   ├── routes.py
│   ├── service.py
│   └── schemas.py
└── products/
    └── ...

按功能或分层组织:

分层组织:
├── routes/(API端点)
├── services/(业务逻辑)
├── models/(数据库模型)
├── schemas/(Pydantic模型)
└── dependencies/(共享依赖)

按功能组织:
├── users/
│   ├── routes.py
│   ├── service.py
│   └── schemas.py
└── products/
    └── ...

5. Django Principles (2025)

5. Django开发原则(2025)

Django Async (Django 5.0+)

Django异步支持(Django 5.0+)

Django supports async:
├── Async views
├── Async middleware
├── Async ORM (limited)
└── ASGI deployment

When to use async in Django:
├── External API calls
├── WebSocket (Channels)
├── High-concurrency views
└── Background task triggering
Django支持的异步特性:
├── 异步视图
├── 异步中间件
├── 异步ORM(有限支持)
├── ASGI部署

在Django中使用异步的场景:
├── 外部API调用
├── WebSocket(搭配Channels)
├── 高并发视图
├── 触发后台任务

Django Best Practices

Django最佳实践

Model design:
├── Fat models, thin views
├── Use managers for common queries
├── Abstract base classes for shared fields

Views:
├── Class-based for complex CRUD
├── Function-based for simple endpoints
├── Use viewsets with DRF

Queries:
├── select_related() for FKs
├── prefetch_related() for M2M
├── Avoid N+1 queries
└── Use .only() for specific fields

模型设计:
├── 胖模型,瘦视图
├── 使用管理器处理通用查询
├── 为共享字段使用抽象基类

视图:
├── 复杂CRUD使用类视图
├── 简单端点使用函数视图
├── 搭配DRF使用视图集

查询优化:
├── 外键查询使用select_related()
├── 多对多查询使用prefetch_related()
├── 避免N+1查询问题
├── 使用.only()获取特定字段

6. FastAPI Principles

6. FastAPI开发原则

async def vs def in FastAPI

FastAPI中的async def vs def

Use async def when:
├── Using async database drivers
├── Making async HTTP calls
├── I/O-bound operations
└── Want to handle concurrency

Use def when:
├── Blocking operations
├── Sync database drivers
├── CPU-bound work
└── FastAPI runs in threadpool automatically
使用async def的场景:
├── 使用异步数据库驱动
├── 发起异步HTTP请求
├── I/O密集型操作
├── 需要处理高并发

使用def的场景:
├── 阻塞操作
├── 使用同步数据库驱动
├── CPU密集型任务
├── FastAPI会自动在线程池中运行

Dependency Injection

依赖注入

Use dependencies for:
├── Database sessions
├── Current user / Auth
├── Configuration
├── Shared resources

Benefits:
├── Testability (mock dependencies)
├── Clean separation
├── Automatic cleanup (yield)
依赖注入的适用场景:
├── 数据库会话
├── 当前用户/身份验证
├── 配置信息
├── 共享资源

优势:
├── 可测试性(模拟依赖)
├── 清晰的关注点分离
├── 自动清理(使用yield)

Pydantic v2 Integration

Pydantic v2集成

python
undefined
python
undefined

FastAPI + Pydantic are tightly integrated:

FastAPI与Pydantic深度集成:

Request validation

请求验证

@app.post("/users") async def create(user: UserCreate) -> UserResponse: # user is already validated ...
@app.post("/users") async def create(user: UserCreate) -> UserResponse: # user已完成验证 ...

Response serialization

响应序列化

Return type becomes response schema

返回类型自动作为响应Schema


---

---

7. Background Tasks

7. 后台任务

Selection Guide

方案选择指南

SolutionBest For
BackgroundTasksSimple, in-process tasks
CeleryDistributed, complex workflows
ARQAsync, Redis-based
RQSimple Redis queue
DramatiqActor-based, simpler than Celery
解决方案适用场景
BackgroundTasks简单、进程内任务
Celery分布式、复杂工作流
ARQ异步、基于Redis
RQ简单Redis队列
Dramatiq基于Actor模型,比Celery更简洁

When to Use Each

各方案的适用场景

FastAPI BackgroundTasks:
├── Quick operations
├── No persistence needed
├── Fire-and-forget
└── Same process

Celery/ARQ:
├── Long-running tasks
├── Need retry logic
├── Distributed workers
├── Persistent queue
└── Complex workflows

FastAPI BackgroundTasks:
├── 快速操作
├── 无需持久化
├── 即发即弃
├── 同进程内执行

Celery/ARQ:
├── 长时间运行的任务
├── 需要重试逻辑
├── 分布式工作节点
├── 持久化队列
├── 复杂工作流

8. Error Handling Principles

8. 错误处理原则

Exception Strategy

异常策略

In FastAPI:
├── Create custom exception classes
├── Register exception handlers
├── Return consistent error format
└── Log without exposing internals

Pattern:
├── Raise domain exceptions in services
├── Catch and transform in handlers
└── Client gets clean error response
FastAPI中的错误处理:
├── 自定义异常类
├── 注册异常处理器
├── 返回统一的错误格式
├── 记录日志但不暴露内部细节

模式:
├── 在服务层抛出领域异常
├── 在处理器中捕获并转换
├── 向客户端返回清晰的错误响应

Error Response Philosophy

错误响应设计原则

Include:
├── Error code (programmatic)
├── Message (human readable)
├── Details (field-level when applicable)
└── NOT stack traces (security)

需包含:
├── 错误码(供程序识别)
├── 错误信息(人类可读)
├── 详细信息(适用时的字段级错误)
└—— 禁止返回堆栈跟踪(安全考虑)

9. Testing Principles

9. 测试原则

Testing Strategy

测试策略

TypePurposeTools
UnitBusiness logicpytest
IntegrationAPI endpointspytest + httpx/TestClient
E2EFull workflowspytest + DB
测试类型目的工具
单元测试测试业务逻辑pytest
集成测试测试API端点pytest + httpx/TestClient
端到端测试测试完整工作流pytest + 数据库

Async Testing

异步测试

python
undefined
python
undefined

Use pytest-asyncio for async tests

使用pytest-asyncio进行异步测试

import pytest from httpx import AsyncClient
@pytest.mark.asyncio async def test_endpoint(): async with AsyncClient(app=app, base_url="http://test") as client: response = await client.get("/users") assert response.status_code == 200
undefined
import pytest from httpx import AsyncClient
@pytest.mark.asyncio async def test_endpoint(): async with AsyncClient(app=app, base_url="http://test") as client: response = await client.get("/users") assert response.status_code == 200
undefined

Fixtures Strategy

Fixture策略

Common fixtures:
├── db_session → Database connection
├── client → Test client
├── authenticated_user → User with token
└── sample_data → Test data setup

常用Fixture:
├── db_session → 数据库连接
├── client → 测试客户端
├── authenticated_user → 带令牌的用户
└── sample_data → 测试数据准备

10. Decision Checklist

10. 决策检查清单

Before implementing:
  • Asked user about framework preference?
  • Chosen framework for THIS context? (not just default)
  • Decided async vs sync?
  • Planned type hint strategy?
  • Defined project structure?
  • Planned error handling?
  • Considered background tasks?

在开始实现前:
  • 询问过用户的框架偏好吗?
  • 是否根据当前场景选择了合适的框架?(而非默认框架)
  • 确定了异步还是同步方案?
  • 规划了类型提示策略?
  • 定义了项目结构?
  • 规划了错误处理方案?
  • 考虑了后台任务需求?

11. Anti-Patterns to Avoid

11. 需避免的反模式

❌ DON'T:

❌ 禁止:

  • Default to Django for simple APIs (FastAPI may be better)
  • Use sync libraries in async code
  • Skip type hints for public APIs
  • Put business logic in routes/views
  • Ignore N+1 queries
  • Mix async and sync carelessly
  • 简单API项目默认使用Django(FastAPI可能更合适)
  • 在异步代码中使用同步库
  • 公共API跳过类型提示
  • 将业务逻辑写在路由/视图中
  • 忽略N+1查询问题
  • 随意混合异步与同步代码

✅ DO:

✅ 推荐:

  • Choose framework based on context
  • Ask about async requirements
  • Use Pydantic for validation
  • Separate concerns (routes → services → repos)
  • Test critical paths

Remember: Python patterns are about decision-making for YOUR specific context. Don't copy code—think about what serves your application best.
  • 根据场景选择框架
  • 询问异步需求
  • 使用Pydantic进行验证
  • 关注点分离(路由→服务→仓库)
  • 测试关键路径

谨记:Python开发模式是针对你的特定场景制定决策。不要复制代码——思考什么最适合你的应用。