python-mypy

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Python mypy — Static Type Checking

Python mypy — 静态类型检查

Mypy is an optional static type checker for Python that catches type errors at development time without runtime overhead. It combines the expressive power of Python with a powerful type system based on PEP 484, enabling gradual migration from dynamic to static typing.
Mypy是一款可选的Python静态类型检查工具,可在开发阶段捕获类型错误,且不会带来运行时开销。它结合了Python的表达能力与基于PEP 484的强大类型系统,支持从动态类型到静态类型的逐步迁移。

Installation

安装

bash
pip install mypy
bash
pip install mypy

Install type stubs for common third-party libraries

为常见第三方库安装类型存根

pip install types-requests types-PyYAML types-boto3
pip install types-requests types-PyYAML types-boto3

Run mypy

运行mypy

mypy src/ mypy --strict src/
undefined
mypy src/ mypy --strict src/
undefined

Core Annotation Patterns

核心注解模式

Functions

函数

Annotate all function signatures — return type and all parameters:
python
from collections.abc import Iterable, Sequence

def process(items: list[str], limit: int = 10) -> list[str]:
    return items[:limit]
为所有函数签名添加注解——包括返回类型和所有参数:
python
from collections.abc import Iterable, Sequence

def process(items: list[str], limit: int = 10) -> list[str]:
    return items[:limit]

Use abstract types for parameters (accept more, restrict less)

为参数使用抽象类型(接受更多类型,限制更少)

def summarize(records: Iterable[dict[str, str]]) -> str: return ", ".join(r["name"] for r in records)
def summarize(records: Iterable[dict[str, str]]) -> str: return ", ".join(r["name"] for r in records)

None return type for procedures

无返回值的过程式函数

def log_event(event: str, level: str = "INFO") -> None: print(f"[{level}] {event}")
undefined
def log_event(event: str, level: str = "INFO") -> None: print(f"[{level}] {event}")
undefined

Optional and Union

可选类型与联合类型

python
undefined
python
undefined

Python 3.10+ syntax (preferred)

Python 3.10+语法(推荐)

def find_user(user_id: int) -> str | None: ...
def find_user(user_id: int) -> str | None: ...

Python 3.9 and earlier

Python 3.9及更早版本

from typing import Optional, Union def find_user(user_id: int) -> Optional[str]: ...
from typing import Optional, Union def find_user(user_id: int) -> Optional[str]: ...

Union for multiple possible types

多可能类型的联合

def normalize_id(user_id: int | str) -> str: if isinstance(user_id, int): return f"user-{user_id}" return user_id
undefined
def normalize_id(user_id: int | str) -> str: if isinstance(user_id, int): return f"user-{user_id}" return user_id
undefined

Classes

python
from typing import ClassVar

class Repository:
    default_limit: ClassVar[int] = 100

    def __init__(self, name: str, url: str) -> None:
        self.name = name
        self.url = url
        self._cache: dict[str, list[str]] = {}

    def fetch(self, query: str) -> list[str]:
        return self._cache.get(query, [])
python
from typing import ClassVar

class Repository:
    default_limit: ClassVar[int] = 100

    def __init__(self, name: str, url: str) -> None:
        self.name = name
        self.url = url
        self._cache: dict[str, list[str]] = {}

    def fetch(self, query: str) -> list[str]:
        return self._cache.get(query, [])

TypedDict for Structured Dicts

结构化字典的TypedDict

Use
TypedDict
instead of
dict[str, Any]
for known-structure dictionaries:
python
from typing import TypedDict

class UserRecord(TypedDict):
    id: int
    name: str
    email: str

class PartialUser(TypedDict, total=False):
    nickname: str
    avatar_url: str

def create_user(data: UserRecord) -> None:
    print(data["name"])  # mypy knows this is str
对于已知结构的字典,使用
TypedDict
替代
dict[str, Any]
python
from typing import TypedDict

class UserRecord(TypedDict):
    id: int
    name: str
    email: str

class PartialUser(TypedDict, total=False):
    nickname: str
    avatar_url: str

def create_user(data: UserRecord) -> None:
    print(data["name"])  # mypy知道此处为str类型

Protocols for Duck Typing

鸭子类型的Protocol

Prefer
Protocol
over concrete base classes for flexible interfaces:
python
from typing import Protocol

class Closeable(Protocol):
    def close(self) -> None: ...

class Readable(Protocol):
    def read(self, n: int = -1) -> bytes: ...

def process_stream(stream: Readable) -> bytes:
    return stream.read()
对于灵活的接口,优先使用
Protocol
而非具体基类:
python
from typing import Protocol

class Closeable(Protocol):
    def close(self) -> None: ...

class Readable(Protocol):
    def read(self, n: int = -1) -> bytes: ...

def process_stream(stream: Readable) -> bytes:
    return stream.read()

Strictness Levels

严格性级别

Adopt strictness incrementally. Start permissive, tighten over time.
逐步提升严格性。从宽松模式开始,随着时间推移逐步收紧。

Recommended Progression

推荐进阶路径

Level 1 — New project baseline (
pyproject.toml
):
toml
[tool.mypy]
python_version = "3.12"
warn_return_any = true
warn_unused_configs = true
warn_unused_ignores = true
Level 2 — Growing codebase:
toml
[tool.mypy]
python_version = "3.12"
warn_return_any = true
warn_unused_configs = true
warn_unused_ignores = true
disallow_incomplete_defs = true
check_untyped_defs = true
Level 3 — Strict (production-ready):
toml
[tool.mypy]
python_version = "3.12"
strict = true
warn_unused_ignores = true
strict
enables:
disallow_untyped_defs
,
disallow_any_generics
,
warn_return_any
,
no_implicit_reexport
,
strict_equality
, and more.
级别1 — 新项目基准
pyproject.toml
):
toml
[tool.mypy]
python_version = "3.12"
warn_return_any = true
warn_unused_configs = true
warn_unused_ignores = true
级别2 — 增长中的代码库
toml
[tool.mypy]
python_version = "3.12"
warn_return_any = true
warn_unused_configs = true
warn_unused_ignores = true
disallow_incomplete_defs = true
check_untyped_defs = true
级别3 — 严格模式(生产就绪)
toml
[tool.mypy]
python_version = "3.12"
strict = true
warn_unused_ignores = true
strict
模式启用以下检查:
disallow_untyped_defs
disallow_any_generics
warn_return_any
no_implicit_reexport
strict_equality
等。

Handling Third-Party Libraries

第三方库处理

Install Type Stubs

安装类型存根

bash
undefined
bash
undefined

Check if stubs are available

检查是否有可用存根

mypy --install-types
mypy --install-types

Install specific stubs

安装特定存根

pip install types-requests types-PyYAML types-redis
undefined
pip install types-requests types-PyYAML types-redis
undefined

Suppress Missing Stubs Per Module

按模块抑制缺失存根的错误

Avoid global
ignore_missing_imports
. Scope it to specific libraries:
toml
undefined
避免全局设置
ignore_missing_imports
,将其限定在特定库:
toml
undefined

pyproject.toml — preferred approach

pyproject.toml — 推荐方式

[[tool.mypy.overrides]] module = ["boto3.", "botocore.", "some_untyped_lib"] ignore_missing_imports = true
undefined
[[tool.mypy.overrides]] module = ["boto3.", "botocore.", "some_untyped_lib"] ignore_missing_imports = true
undefined

Inline Suppression (Use Sparingly)

行内抑制(谨慎使用)

python
import untyped_lib  # type: ignore[import-untyped]

result = complex_dynamic_call()  # type: ignore[no-any-return]  # reason: third-party returns Any
Always add a comment explaining why the suppression is necessary.
python
import untyped_lib  # type: ignore[import-untyped]

result = complex_dynamic_call()  # type: ignore[no-any-return]  # 原因:第三方库返回Any类型
务必添加注释说明抑制错误的必要性。

Common Use Cases

常见使用场景

Migrating an Existing Codebase

迁移现有代码库

Start with zero annotations and progressively type the codebase:
  1. Run
    mypy --ignore-missing-imports src/
    — establish a zero-error baseline.
  2. Enable
    check_untyped_defs = true
    to catch bugs inside unannotated functions.
  3. Add annotations to public API functions first (highest value).
  4. Enable
    disallow_incomplete_defs
    to prevent partially-annotated functions.
  5. Gradually enable
    disallow_untyped_defs
    per package via
    [[tool.mypy.overrides]]
    .
  6. Reach
    strict = true
    as the final goal.
toml
undefined
从无注解开始,逐步为代码库添加类型注解:
  1. 运行
    mypy --ignore-missing-imports src/
    —— 建立零错误基准。
  2. 启用
    check_untyped_defs = true
    以捕获未注解函数内部的bug。
  3. 优先为公共API函数添加注解(价值最高)。
  4. 启用
    disallow_incomplete_defs
    以避免部分注解的函数。
  5. 通过
    [[tool.mypy.overrides]]
    按包逐步启用
    disallow_untyped_defs
  6. 最终目标是启用
    strict = true
toml
undefined

Migrate package-by-package

按包逐步迁移

[[tool.mypy.overrides]] module = "myapp.core.*" disallow_untyped_defs = true
[[tool.mypy.overrides]] module = "myapp.legacy.*" ignore_errors = true # deal with later
undefined
[[tool.mypy.overrides]] module = "myapp.core.*" disallow_untyped_defs = true
[[tool.mypy.overrides]] module = "myapp.legacy.*" ignore_errors = true # 后续处理
undefined

FastAPI / Pydantic Integration

FastAPI / Pydantic集成

python
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float
    tags: list[str] = []
python
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float
    tags: list[str] = []

FastAPI + mypy works seamlessly — Pydantic models are fully typed

FastAPI + mypy无缝协作 —— Pydantic模型是完全类型化的

from fastapi import FastAPI app = FastAPI()
@app.get("/items/{item_id}") async def get_item(item_id: int) -> Item: return Item(name="Widget", price=9.99)
undefined
from fastapi import FastAPI app = FastAPI()
@app.get("/items/{item_id}") async def get_item(item_id: int) -> Item: return Item(name="Widget", price=9.99)
undefined

SQLAlchemy with mypy Plugin

结合mypy插件的SQLAlchemy

toml
[tool.mypy]
plugins = ["sqlalchemy.ext.mypy.plugin"]
python
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column

class Base(DeclarativeBase):
    pass

class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]
    email: Mapped[str | None]
toml
[tool.mypy]
plugins = ["sqlalchemy.ext.mypy.plugin"]
python
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column

class Base(DeclarativeBase):
    pass

class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]
    email: Mapped[str | None]

Type Narrowing

类型收窄

Mypy understands
isinstance
,
assert
, and guard patterns:
python
def render(value: str | int | None) -> str:
    if value is None:
        return ""
    if isinstance(value, int):
        return str(value)
    return value.upper()  # mypy knows: value is str here
Use
reveal_type()
during development to inspect inferred types:
python
x = [1, 2, 3]
reveal_type(x)  # Revealed type is "builtins.list[builtins.int]"
Mypy支持
isinstance
assert
和守卫模式:
python
def render(value: str | int | None) -> str:
    if value is None:
        return ""
    if isinstance(value, int):
        return str(value)
    return value.upper()  # mypy知道:此处value为str类型
开发期间使用
reveal_type()
检查推断的类型:
python
x = [1, 2, 3]
reveal_type(x)  # 显示类型为 "builtins.list[builtins.int]"

CI Integration

CI集成

Pre-commit Hook

预提交钩子

yaml
undefined
yaml
undefined

.pre-commit-config.yaml

.pre-commit-config.yaml

repos:
undefined
repos:
undefined

GitHub Actions

GitHub Actions

yaml
- name: Run mypy
  run: mypy src/ --config-file pyproject.toml
yaml
- name: Run mypy
  run: mypy src/ --config-file pyproject.toml

Quick Reference

速查参考

PatternSyntax
Basic function
def f(x: int) -> str:
Optional param
x: str | None = None
List of strings
list[str]
Dict
dict[str, int]
Callable
Callable[[int, str], bool]
Any iterable
Iterable[str]
Typed dict
class X(TypedDict): key: type
Protocol
class X(Protocol): def method(...):
Suppress line
# type: ignore[error-code]
Debug type
reveal_type(expr)
Forward ref
from __future__ import annotations
FlagPurpose
strict
Enable all optional checks
disallow_untyped_defs
Require all function annotations
check_untyped_defs
Check bodies of unannotated functions
warn_return_any
Warn on implicit
Any
returns
warn_unused_ignores
Catch stale
# type: ignore
comments
ignore_missing_imports
Suppress missing stub errors
模式语法
基础函数
def f(x: int) -> str:
可选参数
x: str | None = None
字符串列表
list[str]
字典
dict[str, int]
可调用对象
Callable[[int, str], bool]
任意可迭代对象
Iterable[str]
类型化字典
class X(TypedDict): key: type
协议
class X(Protocol): def method(...):
行内抑制
# type: ignore[error-code]
调试类型
reveal_type(expr)
前向引用
from __future__ import annotations
标志用途
strict
启用所有可选检查
disallow_untyped_defs
要求所有函数添加注解
check_untyped_defs
检查未注解函数的函数体
warn_return_any
对隐式返回Any类型发出警告
warn_unused_ignores
捕获过时的
# type: ignore
注释
ignore_missing_imports
抑制缺失存根的错误

Additional Resources

额外资源

For complete configuration options and advanced patterns:
  • references/configuration-guide.md
    — Complete
    pyproject.toml
    templates and per-module override patterns
  • references/type-patterns.md
    — Generics, Protocols, TypeVar, ParamSpec, overloads, and advanced patterns
  • examples/pyproject.toml
    — Ready-to-use configuration for new and migrating projects
如需完整配置选项和进阶模式:
  • references/configuration-guide.md
    —— 完整的
    pyproject.toml
    模板和按模块覆盖的模式
  • references/type-patterns.md
    —— 泛型、Protocol、TypeVar、ParamSpec、重载及进阶模式
  • examples/pyproject.toml
    —— 适用于新项目和迁移项目的即用型配置