mypy 2.x 静态类型检查器完全指南:安装使用、类型注解、配置与 Daemon 实战
【免费下载链接】mypyOptional static typing for Python项目地址: https://gitcode.com/GitHub_Trending/my/mypy
本文以 mypy 开源仓库为核心,系统讲解 Python 静态类型检查工具 mypy 的核心理念、安装运行、类型注解语法、命令行与配置文件、增量检查守护进程(daemon)以及 mypyc 编译加速方案。读完本文,你将掌握从零为 Python 项目引入渐进式类型检查的完整实战路径,并理解 mypy 底层工作方式,能够针对大规模代码库制定可行的落地策略。
一、mypy 是什么:Python 的静态类型检查器
Mypy 是 Python 生态中最知名的静态类型检查器(static type checker)。它依据 PEP 484 定义的类型提示(type hints)体系,在不运行代码的前提下分析你的程序,帮助你确认变量与函数的使用方式是否正确。
Python 是一门动态语言,传统上只有在程序运行的那一刻才会暴露类型错误。Mypy 则是"静态"检查器——它不需要执行程序就能发现潜在 bug。这是它与 linter 相似、又与运行时调试截然不同的关键特性。
README 中给出过一个最经典的入门示例:
number = input("What is your favourite number?") print("It is", number + 1) # error: Unsupported operand types for + ("str" and "int")input()返回的是str,而str + int是非法运算。mypy 无需运行程序即可报告Unsupported operand types for + ("str" and "int")。
两个关键事实值得牢记:
- 类型注解不影响运行:为 mypy 添加的类型提示可以看作"高级注释"。即使 mypy 报告了错误,你依然可以随时用 Python 解释器运行代码,两者互不干扰。
- 渐进式类型(gradual typing)设计:mypy 允许你缓慢地为代码库添加类型提示,并且在静态类型不方便的场景下,随时回退到动态类型。这意味着你不需要"一次到位"。
Mypy 拥有强大且易用的类型系统,支持**类型推断、泛型、可调用类型(callable)、元组类型、联合类型(union)、结构化子类型(structural subtyping)**等特性。使用 mypy 能让程序更易于理解、调试和维护。
从仓库源码看,当前开发版本为2.4.0+dev(见 mypy/version.py),入口逻辑位于 mypy/main.py,通过console_entry()调用 mypy/main.py 中的main()完成选项解析与类型检查流程。
二、快速开始:安装与首次运行
Mypy 要求Python 3.10 或更高版本才能运行(见 docs/source/getting_started.rst)。
使用 pip 安装稳定版:
python3 -m pip install -U mypy如果想直接运行仓库中最新代码,可以从仓库源码安装:
python3 -m pip install -U git+https://github.com/python/mypy.git安装完成后,对程序中被静态标注类型的部分执行类型检查:
mypy PROGRAM即使 mypy 报告类型错误,你依然可以照常运行程序:
python3 PROGRAM如果你面对的是大型代码库,可以改用daemon 模式运行 mypy,它通过内存缓存与更细粒度的依赖追踪,让增量检查获得大幅提速(通常可达亚秒级响应):
dmypy run -- PROGRAM你还可以在官方在线游乐场(mypy-play.net,由 Yusuke Miyazaki 开发)中无需安装即可快速试玩 mypy 的检查效果。
三、动态类型与静态类型:渐进式打字的核心理念
在深入命令之前,必须先理解 mypy 的"动态类型 vs 静态类型"判定规则——这是它的核心设计,也是其能安全落地到存量项目的原因。
3.1 无注解的函数默认不被检查
一个没有类型注解的函数,mypy 会将其视为动态类型(dynamically typed):
def greeting(name): return 'Hello ' + name默认情况下,mypy不会检查这类动态类型的函数,这意味着即使你误用了它,mypy 也不会报错:
def greeting(name): return 'Hello ' + name # 程序运行时这两个调用都会失败,但因为 greeting 没有类型注解,mypy 不报告错误 greeting(123) greeting(b"Alice")这正是 README 所说的"可渐进采纳":直接在存量 Python 代码上运行 mypy,它通常几乎不报错——这是特性而非缺陷,它让你可以在小步快跑中引入类型。
3.2 添加注解,激活检查
给函数加上类型提示(type hints)后,它就变成了静态类型(statically typed)函数:
# "name: str" 表示 name 参数应为字符串 # "-> str" 表示 greeting 将返回字符串 def greeting(name: str) -> str: return 'Hello ' + name此时 mypy 会利用注解检查函数内外两端的类型正确性:
def greeting(name: str) -> str: return 'Hello ' + name greeting(3) # Argument 1 to "greeting" has incompatible type "int"; expected "str" greeting(b'Alice') # Argument 1 to "greeting" has incompatible type "bytes"; expected "str" greeting("World!") # No error def bad_greeting(name: str) -> str: return 'Hello ' * name # Unsupported operand types for * ("str" and "str")能够自由决定某个函数是动态类型还是静态类型非常有用:迁移存量代码库时可以逐个函数渐进添加注解;原型开发时可以先动态实现、待稳定后再补全类型。
3.3 收尾与强化命令
迁移或原型开发完成后,可以用以下两个开关约束团队行为:
--disallow-untyped-defs:一旦误加了无注解的动态函数,mypy 立即警告;--check-untyped-defs:对动态类型函数也提供有限度的检查。
更进一步的,mypy 提供strict 模式,启用--strict后你将"基本永远不会在运行时遇到类型错误而 mypy 却没报出来"的情况(除非你显式绕过 mypy)。但对大型存量代码库而言,--strict往往过于激进,建议按 docs/source/existing_code.rst 中的建议分步推进,例如结合--ignore-missing-imports处理大量无类型注解的第三方依赖。
四、更复杂的类型:泛型、Iterable 与联合类型
基本的具体类型(如str、float)之外,mypy 支持表达更丰富的类型语义。
4.1 泛型容器
要表达"字符串列表",使用list[str](Python 3.9 及以上):
def greet_all(names: list[str]) -> None: for name in names: print('Hello ' + name) names = ["Alice", "Bob", "Charlie"] ages = [10, 20, 30] greet_all(names) # Ok! greet_all(ages) # Error due to incompatible typeslist是泛型类型(generic type):它可以接受一个或多个类型参数。通过list[str]参数化后,mypy 就知道greet_all只接受包含字符串的列表。
4.2 面向抽象:Iterable
上面的签名略显死板——该函数完全没必要限定为"列表",传入元组、集合或任意自定义可迭代对象都应正常工作。用collections.abc.Iterable表达:
from collections.abc import Iterable # 或 "from typing import Iterable" def greet_all(names: Iterable[str]) -> None: for name in names: print('Hello ' + name)这正是 PEP 484 类型系统的基础行为:当给变量标注类型T时,实际上是告诉 mypy"该变量可被赋值为T的实例,或T的子类型实例"。例如list[str]就是Iterable[str]的子类型。这一规则同样适用于继承:Child继承自Parent时,Child值可赋给Parent类型变量,例如RuntimeError实例可传给标注为Exception的参数。
4.3 联合类型
要表达"既可以是 int 也可以是 str,但不能是其他",使用联合类型。int是int | str的子类型:
def normalize_id(user_id: int | str) -> str: if isinstance(user_id, int): return f'user-{100_000 + user_id}' else: return user_idtyping模块中还包含大量其他实用类型,完整速查见 docs/source/cheat_sheet_py3.rst,详细类型系统参考见 docs/source/kinds_of_types.rst 与 docs/source/generics.rst。
4.4 导入约定
添加类型时,社区约定采用from typing import <name>形式(而非import typing、import typing as t或from typing import *)。文档示例常省略typing/collections.abc的导入,但实际代码中未导入就使用Iterable等类型会直接报错。另外List(大写)与list(小写)等价,但大写变体是 Python 3.8 及更早版本所必需的。
五、本地类型推断:mypy 自动理解你的代码
一旦函数被标注为静态类型,mypy 就会自动检查函数体,并尽可能推断(infer)细节,无需你写冗余注解。
5.1 isinstance 收窄
上面normalize_id的例子已经展示了这一点:mypy 理解基本的isinstance检查,因此在if分支中推断user_id是int,在else分支中推断是str。这就是常说的类型收窄(type narrowing),详细机制见 docs/source/type_narrowing.rst。
5.2 上下文推断
看这个例子,mypy 仅凭上下文即可推断output为list[float]、num为float,全程无需任何局部变量注解:
def nums_below(numbers: Iterable[float], limit: float) -> list[float]: output = [] for num in numbers: if num < limit: output.append(num) return output类型推断的完整讨论见 docs/source/type_inference_and_annotations.rst。
六、常用类型注解速查
以下核心片段整理自 docs/source/cheat_sheet_py3.rst,覆盖日常 80% 的注解需求。
6.1 变量注解
# 声明变量类型 age: int = 1 # 可以不初始化就注解(运行时在赋值前无值) a: int # 在条件分支中很有用 child: bool if age < 18: child = True else: child = False注意:很多变量注解在技术上其实是冗余的,因为 mypy 通常能从值推断类型。
6.2 内置类型
x: int = 1 x: float = 1.0 x: bool = True x: str = "test" x: bytes = b"test" # 集合:元素类型写在方括号里 x: list[int] = [1] x: set[int] = {6, 7} # 映射:需要键与值的类型 x: dict[str, float] = {"field": 2.0} # 固定长度元组:列出所有元素类型 x: tuple[int, str, float] = (3, "yes", 7.5) # 变长元组:一个类型加省略号 x: tuple[int, ...] = (1, 2, 3) # Python 3.8 及更早版本使用大写形式并从 typing 导入 from typing import List, Set, Dict, Tuple x: List[int] = [1] x: Set[int] = {6, 7} x: Dict[str, float] = {"field": 2.0} x: Tuple[int, str, float] = (3, "yes", 7.5) x: Tuple[int, ...] = (1, 2, 3) from typing import Union, Optional # "或"类型用 | 运算符 x: list[int | str] = [3, 5, "test", "fun"] # Union 与之等价 x: list[Union[int, str]] = [3, 5, "test", "fun"] # 可能为 None 的值用 X | None;Optional[X] 与 X | None 等价 x: str | None = "something" if some_condition() else None if x is not None: # Mypy 依据 if 语句理解此时 x 不会是 None print(x.upper()) # 如果某逻辑 mypy 无法理解、但你确定 x 不可能为 None,用 assert assert x is not None print(x.upper())6.3 函数注解
from collections.abc import Iterator, Callable # 函数定义注解 def stringify(num: int) -> str: return str(num) # 多参数 def plus(num1: int, num2: int) -> int: return num1 + num2 # 无返回值用 None;默认值写在注解之后 def show(value: str, excitement: int = 10) -> None: print(value + "!" * excitement) # 无注解的参数视为动态类型(Any),无注解的函数整体不被检查 def untyped(x): x.anything() + 1 + "string" # no errors # 可调用(函数)值 x: Callable[[int, float], float] = f def register(callback: Callable[[str], int]) -> None: ... # 生成器:产出 int 的生成器本质是返回 int 迭代器的函数 def gen(n: int) -> Iterator[int]: i = 0 while i < n: yield i七、第三方库与 stub 类型包
7.1 标准库开箱即用
Mypy 自带对 Python 标准库的深入理解。例如下面这个使用pathlib.Path的函数,mypy 知道Path有返回str的read_text()方法:
from pathlib import Path def load_template(template_path: Path, name: str) -> str: # Mypy 知道 template_path 有 read_text 方法且返回 str template = template_path.read_text() # ... 因此这一行能通过类型检查 return template.replace('USERNAME', name)7.2 缺失类型信息的三方库
若第三方库声明支持类型检查(打包了类型标注),mypy 会基于其中的类型提示检查你的用法(详见 docs/source/installed_packages.rst)。但如果库没有类型提示,mypy 会抱怨缺少类型信息:
prog.py:1: error: Library stubs not installed for "yaml" prog.py:1: note: Hint: "python3 -m pip install types-PyYAML" prog.py:2: error: Library stubs not installed for "requests" prog.py:2: note: Hint: "python3 -m pip install types-requests" ...此时可通过安装stub 包为 mypy 提供类型信息来源。stub 包只含另一库的类型提示、不含实际代码:
python3 -m pip install types-PyYAML types-requestsstub 包命名规律通常是types-<distribution>,注意发行名可能与导入名不同——例如types-PyYAML提供的其实是yaml包的 stub。更多缺失导入的处理策略见 docs/source/common_issues.rst,stub 文件机制详见 docs/source/stubs.rst。本仓库自带的typeshed类型标注集合位于 mypy/typeshed/stdlib(标准库.pyistub)与 mypy/typeshed/stubs(第三方 stub),它们是 mypy 内置类型知识的来源。
八、命令行参考:指定检查目标与常用开关
完整的命令行文档见 docs/source/command_line.rst,可通过mypy --help快速查看全部 flag 摘要。
8.1 指定要检查什么
默认方式:直接传入文件、目录(目录会被递归检查):
mypy foo.py bar.py some_directory其他指定方式:
| 参数 | 行为 |
|---|---|
-m MODULE, --module MODULE | 检查指定模块(可重复),不会递归检查其子模块 |
-p PACKAGE, --package PACKAGE | 检查指定包(可重复),会递归检查子模块,其余与--module相同 |
-c PROGRAM_TEXT, --command PROGRAM_TEXT | 将给定字符串当作程序进行检查 |
--exclude REGEX | 正则匹配文件名/目录名/路径,在递归发现时忽略;不影响显式传入的文件,也不影响 import following |
--exclude-gitignore | 把.gitignore匹配的所有内容加入--exclude |
--exclude示例:忽略所有setup.py、build目录与project/vendor子路径,但强制检查某个具体文件:
mypy --exclude '/setup\.py$' --exclude '/build/' --exclude '/project/vendor/' but_still_check/setup.py注意:mypy 永远不会递归发现名为site-packages、node_modules、__pycache__或点开头的目录/文件,也只会递归发现.py与.pyi后缀的文件。
8.2 常用开关
-h, --help:显示帮助并退出;-v, --verbose:更详细的输出;-V, --version:显示版本号。-O json, --output json:设置自定义输出格式(目前支持 JSON)。--config-file CONFIG_FILE:从指定文件读取配置;--config-file=(不带文件名)表示忽略所有配置文件;--warn-unused-configs则对未使用的[mypy-<pattern>]配置节发出警告。--strict:开启严格模式(等价于启用--disallow-untyped-defs等一系列附加检查)。--ignore-missing-imports:忽略所有缺失导入,等价于给所有未解析 import 加# type: ignore(但不抑制已解析模块内的缺失名称错误)。
其余大量开关覆盖 import 发现、错误码、增量缓存、报告输出等维度,例如--explicit-package-bases(在无__init__.py场景下声明顶级包基准目录)与--follow-imports系列。错误码的完整清单见 docs/source/error_code_list.rst。
九、配置文件:mypy.ini 与每模块细粒度控制
Mypy 高度可配置,这一点在给存量代码库引入类型时尤为重要。完整的配置文档见 docs/source/config_file.rst。
9.1 配置文件查找顺序
默认情况下,mypy 沿文件系统向上(直到仓库根或文件系统根)依次查找:
mypy.ini.mypy.inipyproject.toml(包含[tool.mypy]节)setup.cfg(包含[mypy]节)
若以上皆无,则在用户级目录查找:$XDG_CONFIG_HOME/mypy/config、~/.config/mypy/config、~/.mypy.ini。
--config-file命令行选项优先级最高且必须指向有效文件,否则 mypy 报错退出。配置文件之间不进行合并,以避免歧义。配置文件中路径支持~开头(用户主目录)与$VARNAME/${VARNAME}环境变量展开。
9.2 格式与两种节
配置文件是标准 INI 格式:方括号节名 +NAME = VALUE,#开头为注释。
[mypy]节(必须存在):定义全局 flags。[mypy-PATTERN1,PATTERN2,...]节(可选):PATTERN 是全限定模块名模式,部分组件可用*替换(如foo.bar、foo.bar.*、foo.*.baz)。这些节定义的 flags 只作用于名字匹配至少一个模式的模块。
模式匹配规则:qualified_module_name只匹配指定模块;dotted_module_name.*匹配该模块及其所有子模块(foo.bar.*可匹配foo.bar、foo.bar.baz、foo.bar.baz.quux);也支持中间出现星号的无结构通配(site.*.migrations.*,星号匹配零个或多个模块组件)。
9.3 配置优先级
当选项冲突时,优先级从高到低为:
- 源码文件内的内联配置(见 docs/source/inline_config.rst)
- 具体模块名节(
foo.bar) - 无结构通配节(
foo.*.baz),文件内靠后的节覆盖靠前的节 - 结构良好的通配节(
foo.bar.*),更具体的覆盖更一般的 - 命令行选项
- 顶层配置文件选项
9.4 完整示例
# Global options: [mypy] warn_return_any = True warn_unused_configs = True # Per-module options: [mypy-mycode.foo.*] disallow_untyped_defs = True [mypy-mycode.bar] warn_return_any = False [mypy-somelibrary] ignore_missing_imports = True其效果为:
- 全局:函数返回被推断为
Any的值时报告错误; - 全局:报告未被 mypy 使用的配置选项(帮助捕获配置拼写错误);
- 在
mycode/foo目录下的模块内,选择性禁止无注解的函数定义; - 仅对
mycode.bar模块关闭"返回 any"警告(覆盖上面的全局默认值); - 抑制导入
somelibrary时产生的错误消息——适用于缺少类型提示的第三方库。
布尔选项可通过加no_前缀反转,或在适用时把disallow前缀换成allow(反之亦然)。
9.5 全局专属选项与每模块选项
从源码角度看,哪些选项支持 per-module 设置是硬编码的:mypy/options.py中的PER_MODULE_OPTIONS集合(见 mypy/options.py)罗列了全部可按模块覆盖的选项,其中包括disallow_untyped_defs、check_untyped_defs、ignore_missing_imports、follow_imports、ignore_errors、allow_redefinition、strict_equality等数十项。
以下选项只能在全局[mypy]节设置:
mypy_path:指定在MYPYPATH环境变量之后尝试的搜索路径,多路径用:或,分隔;可用MYPY_CONFIG_FILE_DIR环境变量引用相对配置文件的位置(如mypy_path = $MYPY_CONFIG_FILE_DIR/src)。files:逗号分隔的路径列表,支持 glob 递归匹配(*.py匹配当前目录,**/*.py匹配所有子目录)。modules/packages:与-m/-p对应的配置形式(packages会递归检查子模块)。exclude:与--exclude等价的正则,可用(?x)VERBOSE 模式编写多行可读表达式。
本仓库自身的类型检查配置可参考 mypy_self_check.ini 与 mypy_bootstrap.ini。
十、mypy daemon:亚秒级增量检查的守护进程模式
大型代码库上,反复运行mypy命令行工具的代价很高。README 推荐使用 daemon 模式,完整文档见 docs/source/mypy_daemon.rst。
10.1 为什么更快
与其每次从命令行冷启动,mypy daemon 把类型检查器作为常驻服务运行,客户端通过命令行工具向服务发送检查请求。前一次运行的程序状态被缓存在内存中,无需每次从文件系统重新读取;服务端还使用更细粒度的依赖追踪来减少工作量。文档指出:检查大型代码库时,daemon 模式可以比常规mypy快 10 倍以上,尤其适合"小幅编辑后反复检查"的工作流。
注意事项:每个 daemon 进程只服务一个用户和一组源文件,且同一时刻只能处理一个检查请求;如需检查多个仓库,可以运行多个 daemon 进程。
10.2 基本用法
客户端工具dmypy用于控制 daemon:
dmypy run -- prog.py pkg/*.pydmypy run -- <flags> <files>会检查一组文件(或目录),若 daemon 未运行则自动启动它;--之后几乎可以放任意 mypy flags。配置或 mypy 版本变化时,dmypy run会自动重启 daemon。首次运行会处理全部代码、耗时较长,后续运行(尤其只改动少量文件时)会很快。
10.3 客户端命令
dmypy stop:停止 daemon。dmypy start -- <flags>:启动 daemon 但不检查任何文件。dmypy restart -- <flags>:重启 daemon(等价于 stop 后 start)。dmypy check <files>:用已运行的 daemon 检查一组文件。dmypy recheck:重新检查最近一次check/recheck的文件集合;可用--update FILE与--remove FILE调整文件集合(适用于外部文件系统监听器如 watchman/watchdog 的场景,属性能调优选项)。dmypy status:查询 daemon 是否在运行,有则打印诊断信息并以退出码 0 结束。
dmypy --help可查看其余命令,dmypy <command> --help可查看命令专属选项。
10.4 守护进程附加参数
--status-file FILE:指定存放 daemon 运行状态的 JSON 文件(含进程与连接信息),默认为当前目录下的.dmypy.json。--log-file FILE:把 daemon 的 stdout/stderr 重定向到文件,便于调试崩溃(start/restart/run可用)。--timeout SECONDS:空闲SECONDS秒后自动关停 daemon(默认一直运行直到显式停止)。--perf-stats-file FILE:将性能剖析信息写入文件(check/recheck/run可用)。--export-types:把所有表达式类型存入内存,加速后续dmypy inspect(会占用更多内存)。
10.5 dmypy suggest:自动推断函数签名
daemon 还支持实验性的静态推断注解能力:dmypy suggest FUNCTION可为无注解函数生成草案签名,格式为(param_type_1, param_type_2, ...) -> ret_type(覆盖所有参数,含 keyword-only、*args、**kwargs)。例如:
def format_id(user): return f"User: {user}" root = format_id(0)运行dmypy suggest module.format_id会结合调用点、return 语句、基类签名等启发式信息,推断出format_id接受int、返回str。目标函数可用全限定名([package.]module.[class.]function)或文件位置(/path/to/file.py:line)指定。相关选项:--json(输出 JSON 供 PyAnnotate 消费)、--no-errors(只产出不引发类型错误的建议)、--no-any(建议不含Any)、--flex-any FRACTION(允许一定比例的Any)、--callsites(仅列出调用点)。这一底层特性主要面向编辑器/IDE 集成(如 PyCharm mypy 插件)的自动补全。其客户端实现位于 mypy/dmypy/client.py,服务端状态管理与检查逻辑见 mypy/dmypy_server.py。
十一、IDE 与工具链集成
Mypy 可以融入主流开发工具,README 列出如下集成方式:
- VS Code:Python 扩展提供与 mypy 的基础集成。
- Vim:
- Syntastic:在
~/.vimrc添加let g:syntastic_python_checkers=['mypy'] - ALE:安装 mypy 后通常默认启用,也可在
~/vim/ftplugin/python.vim显式添加let b:ale_linters = ['mypy']
- Syntastic:在
- Emacs:通过 Flycheck 集成。
- Sublime Text:使用 SublimeLinter-contrib-mypy。
- PyCharm:使用 mypy 插件。
- IDLE:使用 idlemypyextension 扩展。
- pre-commit:使用 pre-commit 的 mirrors-mypy 钩子——注意默认情况下这会限制 mypy 分析第三方依赖的能力。
CI 场景下,本仓库还提供了 GitHub Actions 复用配置 action.yml。
十二、Mypyc:用 mypy 编译 mypy 自身
README 专门介绍了 Mypyc 项目:它利用 Python 类型提示把 Python 模块编译为更快的 C 扩展。Mypy 自身就是用 mypyc 编译的,这使得 mypy 比解释执行时大约快 4 倍。
如需安装解释执行的 mypy,使用:
python3 -m pip install --no-binary mypy -U mypy若希望直接使用开发版本 mypy 的编译产物,可从 mypyc 项目发布的 wheel 直接安装。
本仓库包含完整的 mypyc 编译器实现,可作为研究其原理的第一手资料:核心 IR 定义在 mypyc/ir,Python 到 IR 的构建逻辑在 mypyc/irbuild,C 代码生成在 mypyc/codegen,运行时支持库(CPy.h及各类原生操作实现)在 mypyc/lib-rt,优化变换(引用计数、拷贝传播、flag 消除、spill 等)在 mypyc/transform,测试用例则在 mypyc/test-data。
十三、参与贡献与继续深入
Mypy 欢迎各种经验水平的贡献者参与测试、开发、文档等工作。上手贡献的完整指南见 CONTRIBUTING.md。运行测试套件的入口是 runtests.py,依赖列表见 test-requirements.txt。
按主题深入阅读仓库内文档(位于 docs/source):
- docs/source/cheat_sheet_py3.rst:类型提示速查表
- docs/source/getting_started.rst:入门教程(动态/静态类型、泛型、联合类型、库类型)
- docs/source/command_line.rst:命令行完整参考
- docs/source/config_file.rst:配置文件完整参考
- docs/source/mypy_daemon.rst:daemon 模式完整参考
- docs/source/error_code_list.rst:错误码清单
- docs/source/common_issues.rst:常见问题与解决方案
- docs/source/existing_code.rst:存量代码库接入策略
- docs/source/stubs.rst:stub 文件机制
- docs/source/generics.rst、docs/source/protocols.rst、docs/source/type_narrowing.rst:类型系统进阶主题
核心源码路径速览:入口 mypy/main.py、主流程 mypy/main.py、选项模型 mypy/options.py、类型检查核心 mypy/checker.py 与 mypy/checkexpr.py、类型表示 mypy/types.py、语义分析 mypy/semanal.py、错误码定义 mypy/errorcodes.py。
结语
从一行pip install mypy到大规模代码库的渐进式迁移,mypy 通过"动态/静态类型自由切换"的设计、丰富的类型系统、可精细到模块级的配置体系,以及 daemon 与 mypyc 双重性能方案,构成了一个完整、可落地的 Python 静态类型检查解决方案。本文所覆盖的安装运行、注解语法、命令行与配置、daemon 实战,足以支撑你在真实项目中安全起步,而仓库内 docs/source 的系列文档与 mypy 目录下的源码,则为深度研究提供了完整的一手材料。
【免费下载链接】mypyOptional static typing for Python项目地址: https://gitcode.com/GitHub_Trending/my/mypy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考