page contents

Python 项目越来越大,类型检查又重新火起来了

Python 一直都是最容易上手的语言之一。你可以在不声明任何类型的情况下编写函数,可以传递不同类型的对象,也可以用很少的代码让程序运行起来。这种灵活性也是 Python 在 Web 开发、数据科学、自动化和 AI 领域如此流行的原因之一。

attachments-2026-10-0eoXgDjQ6acd86b053f35.png

Python 一直都是最容易上手的语言之一。

你可以在不声明任何类型的情况下编写函数,可以传递不同类型的对象,也可以用很少的代码让程序运行起来。这种灵活性也是 Python 在 Web 开发、数据科学、自动化和 AI 领域如此流行的原因之一。

但它也有代价。

当一个 Python 项目从几千行增长到几十万行,甚至几百万行时,理解数据和对象是如何在整个系统中流动的,会变得越来越困难。

这就是类型检查再次变得重要的地方。

最近的调查和工程实践报告表明,Python typing 已经不再只是那些来自静态类型语言的开发者才会使用的小众实践。它已经成为大型 Python 代码库的一部分,而新一代更快的 type checker 也让相关工具越来越有吸引力。

Python Typing 已经被广泛使用

Python 的 type hints 并不是什么新东西。

PEP 484 在 2015 年奠定了现代 Python typing 的基础。从那以后,typing 系统持续发展,加入了 generics、TypedDict、Protocol、TypeGuard、TypeIs,以及不断改进的 type alias 和 union 语法。

Python 本身仍然是动态类型语言。Python 解释器不会自动强制执行 type annotations。相反,它们提供的信息可以被 static type checker、IDE、linter 以及其他工具使用。

发生变化的是开发者使用这些功能的方式。

Meta 的 2025 Python Typing Survey 收集了 1,241 份回复。其中,86% 的受访者表示他们“总是”或“经常”使用 type hints。调查还发现,Mypy 仍然是使用最广泛的 type checker,而 Pyrefly、Ty 和 Zuban 等较新的工具也开始获得关注。需要注意的是,这项调查也指出,它的受访者可能比整个 Python 开发者群体更加熟悉 typing。

这并不意味着每个 Python 项目都需要严格 typing。

但它确实说明,typing 已经远远超出了一个实验性功能的范围。

代码库越大,类型的价值越高

原因很简单:大型系统中的关系太多,开发者不可能全部记在脑子里。

看一个简单的函数:

def get_user_role(user_id):
    user = load_user(user_id)

    if not user:
        return None

    return user.role

这段代码完全合法。

但当项目变大以后会发生什么?

一个调用方可能认为 user_id 是整数。另一个调用方可能传入字符串。

一个调用方可能认为 get_user_role() 始终返回字符串。另一个调用方可能忘记它也可能返回 None。

这些问题都不一定能从函数内部直接看出来。

问题存在于程序不同部分之间的边界上。

Static type checking 在这里尤其有用,因为它可以分析函数和模块之间的关系,而不是只单独查看每一个函数。

对于一个小项目,开发者通常可以手动理解这些关系。

但对于一个拥有数百万行代码的代码库来说,这会困难得多。

大型公司正在给数百万行 Python 加类型

这种趋势在大型工程组织中尤其明显。

2026 年 4 月,Eightfold 分享了他们在一个超过 400 万行代码的 Python monorepo 中引入 static type checking 的实践。

他们并没有尝试一次性给整个代码库添加类型注解。

相反,他们结合了 gradual typing、使用 MonkeyType 进行自动类型推断、自定义的 Mypy 配置以及两层 CI 系统。MonkeyType 通过在运行时观察函数调用和返回值来收集类型信息,然后利用这些信息生成 annotations 或 stubs。目标是在不阻塞整个组织开发的情况下,引入有价值的静态分析。

Kraken 的代码库规模更大。

它的主 monorepo 包含超过 1,000 万行代码,其中包括测试代码,大约 500 万行 Python 代码由 Mypy 进行检查。这个代码库还包含超过 2,000 个 Django models。

让 Django 和 static typing 一起工作并不简单,因为 Django 大量使用了动态行为。

Kraken 最终开发了自己的 Mypy plugin 和其他工具来处理其中一些情况。经过多年的努力,他们表示在相关代码库中已经实现了 zero missing annotations,但仍然存在一些 Any 的使用以及类型检查抑制。

这些例子说明了一件重要的事情。

在这样的规模下,类型检查已经不再主要是为了让单个函数更容易阅读。

它开始成为安全修改大型系统所需要的工程基础设施的一部分。

类型检查同样与重构有关

类型最大的价值之一,会在开发者修改现有代码时体现出来。

假设一个函数最初是这样的:

def calculate_price(product):
    ...

后来变成:

def calculate_price(product: Product) -> Decimal:
    ...

现在,预期的接口就明确了。

如果应用程序的其他部分传入了不兼容的对象,type checker 可以在代码进入生产环境之前报告这个问题。

同样的事情在重构过程中会更加有价值。

重命名一个 class。

修改一个函数的返回类型。

用一个接口替换另一个接口。

拆分一个 module。

修改一个 configuration object 的结构。

在一个类型覆盖充分的代码库中,type checker 可以成为一张关系地图,告诉你哪些地方需要一起修改。

这也是 Python typing specification 将 static analysis 和 refactoring 作为类型系统重要目标的原因之一。

类型不仅仅是文档。

它们可以成为程序不同部分之间机器可读的契约。

工具也在发生变化

类型检查重新受到关注,还有一个原因:工具本身正在变得更快。

Mypy 仍然是生态中占主导地位的工具之一,但它已经不再是唯一一个重要的选择。

Pyright 由 Microsoft 开发,在设计时就考虑了性能和 language-server 集成。它的文档指出,在某些情况下,在大型代码库上它可以明显快于 Mypy。

Meta 也一直在开发 Pyrefly,这是一个使用 Rust 编写的 type checker。

这个项目源于 Meta 在 Instagram 规模上使用 typed Python 的经验。Meta 表示,他们的目标是构建一个能够处理大型 monorepository,同时在开发过程中保持响应速度的 type checker 和 language-server 体验。

与此同时,Python typing 生态中现在已经出现了多个 type checker 以及相关工具。

Python typing 文档目前列出了 Mypy、Pyright、Pyrefly、Ty 和 Zuban 这些可用的 type checker。

与几年前的 Python typing 生态相比,这是一个明显的变化。

现在的问题已经不再只是:

“我应该使用 Mypy 吗?”

而越来越变成:

“哪一种 type-checking workflow 更适合这个项目?”

Gradual Typing 让迁移成为可能

这里仍然存在一个主要问题。

大多数大型 Python 项目从一开始就没有使用 static typing 编写。

手动给几十万甚至几百万行代码添加类型,成本可能非常高。

幸运的是,Python 的 typing 系统是 gradual 的。

你可以从代码库的一小部分开始:

def get_user(user_id: int) -> User:
    ...

然后逐渐扩大覆盖范围。

你可以先给 public APIs 添加类型。

可以给新的 modules 添加类型,同时保留旧的 modules 不动。

可以只针对选定的 packages 引入检查。

也可以逐渐提高 configuration 的严格程度。

这种方式与一夜之间把 Python 项目转换成完全静态类型语言有本质区别。

Python typing specification 明确支持 gradual typing,这意味着一个程序中可以同时存在 static typed 和 dynamic typed 的部分。

这让 typing 特别适合长期维护的 Python 项目。

AI 让类型信息变得更加有用

Python typing 和 AI-assisted programming 的兴起之间,还有一个有趣的联系。

AI coding tools 可以快速生成代码。

但生成的代码仍然需要融入现有代码库。

这意味着理解 interfaces、function signatures、return types、protocols 和 data structures 变得越来越重要。

Type checker 可以充当一个自动化反馈循环。

工作流程可能是这样的:

AI generates code
       ↓
Type checker analyzes it
       ↓
Errors are reported
       ↓
Code is corrected
       ↓
Tests run
       ↓
Code is reviewed

这并不意味着类型检查可以取代测试。

类型无法告诉你业务规则是否正确,无法告诉你 SQL 查询是否返回了正确的数据,也无法告诉你 API 的行为是否符合预期。

但它们可以在运行之前捕获一整类接口和一致性错误,让测试能够更多地关注行为和业务逻辑。

随着 AI 生成的代码越来越普遍,快速的静态反馈可能会变得更加有用。

类型并不是没有成本的

重新受到关注的 typing 并不意味着 Python 的类型系统已经解决了所有问题。

2025 年的调查指出了几个持续存在的问题。

第三方库可能存在不完整或不准确的类型信息。

Generics、decorators、TypeVar 以及复杂的嵌套类型等高级功能可能很难理解。

在 specification 没有定义每一个细节的情况下,不同的 type checker 可能表现不同。

Legacy code 和高度动态的 framework 也可能很难添加类型。

开发者也一直在讨论到底添加多少 annotation 才算过多。

这些问题在大量依赖运行时行为的 framework 中尤其明显。

Django 就是一个很好的例子。

Kraken 的实践表明,要让一个大型 Django 应用实现 strong typing,需要额外的工具,因为一些只存在于运行时的信息很难被 static analyzer 自动确定。

所以,添加类型并不会自动让项目变得更好。

设计不合理的类型,只是可能把复杂度从运行时代码转移到了类型声明中。

目标不是“Maximum Typing”

人们很容易把 typing 变成一个简单的指标:

“Annotation 越多越好。”

大型 Python 项目提供了一种更有价值的思考方式。

目标不是给每一个可能的变量都添加 annotation。

目标是让重要的 interfaces 足够明确,使开发者和工具能够理解整个系统。

Public APIs 通常是很好的目标。

团队之间共享的 functions 是很好的目标。

Core domain models 是很好的目标。

经常发生变化的代码通常值得添加类型。

高度动态的 legacy code 可能需要采用不同的策略。

换句话说,typing 的价值很大程度上取决于类型被放在哪里。

在重要边界上添加少量有价值的类型,有时比机械地添加数千个 annotation 更有价值。

Python 还是 Python

类型检查重新受到关注,并不意味着 Python 正在变成 Java 或 C++。

Python 仍然是动态类型语言。

你依然可以这样写:

x = 10
x = "hello"

解释器并不要求你声明 x 的类型。

当动态特性有用时,你仍然可以使用它们。

区别在于,成熟的 Python 项目现在越来越有能力在这个动态语言之上增加一层静态分析。

这一层可以帮助开发者理解大型系统、发现接口错误、改善 IDE 支持,并让重构更加安全。

而且由于类型系统是 gradual 的,项目可以逐步采用它,而不需要一次性改变所有东西。

Python 越来越大,类型也越来越重要

Python 最初的优势就是简单。

写一些代码,运行它,然后快速迭代。

当程序规模较小时,这种模式非常有效。

但现代 Python 已经不再局限于小型脚本。

Python 现在支撑着大型 Web 服务、数据平台、科学应用、AI 系统、内部基础设施,以及包含数百万行代码的 monorepositories。

在这种规模下,最大的问题往往已经不再是写代码。

而是理解现有代码之间是如何组合在一起的。

这正是类型检查变得有价值的地方。

当前的 Python 生态正在朝着一个有意思的方向发展:语言本身保持动态,而围绕它的开发环境则拥有越来越强的静态分析能力。

更快的 type checkers、更好的 IDE 集成、更丰富的 typing 功能、更完善的库类型注解,以及大规模采用,都在推动这个方向的发展。

Python 不需要停止成为动态语言。

但随着 Python 项目不断变大,开发者越来越需要一些方法,让这个动态世界更容易被人和机器理解。

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

 

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

2480 篇文章

作家榜 »

  1. Pack 2480 文章
  2. 轩辕小不懂 2403 文章
  3. 小柒 2228 文章
  4. Nen 576 文章
  5. 王昭君 216 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章