python
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePython Skill
Python开发技能指南
Load with: base.md
需配合base.md使用
Type Hints
类型提示
- Use type hints on all function signatures
- Use module for complex types
typing - Run in CI
mypy --strict
python
def process_user(user_id: int, options: dict[str, Any] | None = None) -> User:
...- 所有函数签名都使用类型提示
- 对复杂类型使用模块
typing - 在CI中运行
mypy --strict
python
def process_user(user_id: int, options: dict[str, Any] | None = None) -> User:
...Project Structure
项目结构
project/
├── src/
│ └── package_name/
│ ├── __init__.py
│ ├── core/ # Pure business logic
│ │ ├── __init__.py
│ │ ├── models.py # Pydantic models / dataclasses
│ │ └── services.py # Pure functions
│ ├── infra/ # Side effects
│ │ ├── __init__.py
│ │ ├── api.py # FastAPI routes
│ │ └── db.py # Database operations
│ └── utils/ # Shared utilities
├── tests/
│ ├── unit/
│ └── integration/
├── pyproject.toml
└── CLAUDE.mdproject/
├── src/
│ └── package_name/
│ ├── __init__.py
│ ├── core/ # 纯业务逻辑
│ │ ├── __init__.py
│ │ ├── models.py # Pydantic 模型 / 数据类
│ │ └── services.py # 纯函数
│ ├── infra/ # 副作用处理
│ │ ├── __init__.py
│ │ ├── api.py # FastAPI 路由
│ │ └── db.py # 数据库操作
│ └── utils/ # 共享工具类
├── tests/
│ ├── unit/
│ └── integration/
├── pyproject.toml
└── CLAUDE.mdTooling (Required)
必备工具
toml
undefinedtoml
undefinedpyproject.toml
pyproject.toml
[tool.ruff]
line-length = 100
select = ["E", "F", "I", "N", "W", "UP"]
[tool.mypy]
strict = true
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--cov=src --cov-report=term-missing --cov-fail-under=80"
---[tool.ruff]
line-length = 100
select = ["E", "F", "I", "N", "W", "UP"]
[tool.mypy]
strict = true
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--cov=src --cov-report=term-missing --cov-fail-under=80"
---Testing with Pytest
使用Pytest进行测试
python
undefinedpython
undefinedtests/unit/test_services.py
tests/unit/test_services.py
import pytest
from package_name.core.services import calculate_total
class TestCalculateTotal:
def test_returns_sum_of_items(self):
# Arrange
items = [{"price": 10}, {"price": 20}]
# Act
result = calculate_total(items)
# Assert
assert result == 30
def test_returns_zero_for_empty_list(self):
assert calculate_total([]) == 0
def test_raises_on_invalid_item(self):
with pytest.raises(ValueError):
calculate_total([{"invalid": "item"}])
---import pytest
from package_name.core.services import calculate_total
class TestCalculateTotal:
def test_returns_sum_of_items(self):
# 准备
items = [{"price": 10}, {"price": 20}]
# 执行
result = calculate_total(items)
# 断言
assert result == 30
def test_returns_zero_for_empty_list(self):
assert calculate_total([]) == 0
def test_raises_on_invalid_item(self):
with pytest.raises(ValueError):
calculate_total([{"invalid": "item"}])
---GitHub Actions
GitHub Actions 配置
yaml
name: Python Quality Gate
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install -e ".[dev]"
- name: Lint (Ruff)
run: ruff check .
- name: Format Check (Ruff)
run: ruff format --check .
- name: Type Check (mypy)
run: mypy src/
- name: Test with Coverage
run: pytestyaml
name: Python Quality Gate
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install -e ".[dev]"
- name: Lint (Ruff)
run: ruff check .
- name: Format Check (Ruff)
run: ruff format --check .
- name: Type Check (mypy)
run: mypy src/
- name: Test with Coverage
run: pytestPre-Commit Hooks
预提交钩子
yaml
undefinedyaml
undefined.pre-commit-config.yaml
.pre-commit-config.yaml
repos:
-
repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.8.0 hooks:
- id: ruff args: [--fix]
- id: ruff-format
-
repo: https://github.com/pre-commit/mirrors-mypy rev: v1.13.0 hooks:
- id: mypy additional_dependencies: [pydantic] args: [--strict]
-
repo: local hooks:
- id: pytest name: pytest entry: pytest tests/unit -x --tb=short language: system pass_filenames: false always_run: true
Install and setup:
```bash
pip install pre-commit
pre-commit installrepos:
-
repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.8.0 hooks:
- id: ruff args: [--fix]
- id: ruff-format
-
repo: https://github.com/pre-commit/mirrors-mypy rev: v1.13.0 hooks:
- id: mypy additional_dependencies: [pydantic] args: [--strict]
-
repo: local hooks:
- id: pytest name: pytest entry: pytest tests/unit -x --tb=short language: system pass_filenames: false always_run: true
安装与配置:
```bash
pip install pre-commit
pre-commit installPatterns
设计模式
Pydantic for Data Validation
使用Pydantic进行数据校验
python
from pydantic import BaseModel, Field
class CreateUserRequest(BaseModel):
email: str = Field(..., min_length=5)
name: str = Field(..., max_length=100)python
from pydantic import BaseModel, Field
class CreateUserRequest(BaseModel):
email: str = Field(..., min_length=5)
name: str = Field(..., max_length=100)Dependency Injection
依赖注入
python
undefinedpython
undefinedDon't import dependencies directly in business logic
不要在业务逻辑中直接导入依赖
Pass them in
而是通过参数传入
Bad
错误示例
from .db import database
def get_user(user_id: int) -> User:
return database.fetch(user_id)
from .db import database
def get_user(user_id: int) -> User:
return database.fetch(user_id)
Good
正确示例
def get_user(user_id: int, db: Database) -> User:
return db.fetch(user_id)
undefineddef get_user(user_id: int, db: Database) -> User:
return db.fetch(user_id)
undefinedResult Pattern (No Exceptions in Core)
结果模式(核心逻辑中不使用异常)
python
from dataclasses import dataclass
@dataclass
class Result[T]:
value: T | None
error: str | None
@property
def is_ok(self) -> bool:
return self.error is Nonepython
from dataclasses import dataclass
@dataclass
class Result[T]:
value: T | None
error: str | None
@property
def is_ok(self) -> bool:
return self.error is NonePython Anti-Patterns
Python 反模式
- ❌
from module import * - ❌ Mutable default arguments
- ❌ Bare clauses
except: - ❌ Using without explanation
type: ignore - ❌ Global variables for state
- ❌ Classes when functions suffice
- ❌ (通配符导入)
from module import * - ❌ 可变默认参数
- ❌ 裸语句
except: - ❌ 无说明地使用
type: ignore - ❌ 使用全局变量存储状态
- ❌ 能用函数实现却使用类