Python 类型提示的演变史

Python 类型提示(type hints)大致可以分成几个阶段,每个阶段背后都有不同目标:文档化 → 静态分析 → 泛型系统 → 类型表达力增强 → 类型系统趋近现代语言


Python 类型提示的演变史

一、史前时代:类型靠约定(Python 3.5 以前)

早期 Python 是纯动态类型语言:

def add(a, b):
    return a + b

类型完全依赖:

  • 命名约定(user_id, str_name
  • Docstring
def greet(name):
    """
    :type name: str
    :rtype: str
    """

Sphinx / Epydoc 风格

这其实算最早的“类型提示”。

特点:

  • 只给人看
  • IDE 勉强利用
  • 没有语言级支持

二、函数注解出现(PEP 3107, Python 3.0,2008)

真正转折点:

PEP 3107

引入:

def greet(name: str) -> str:
    return "Hello " + name

但关键点:

这不是类型系统。

只是“给参数挂元数据”。

def foo(x: "anything"):
    ...

Python 本身不检查类型。

设计哲学:

注解语法先落地,用途以后再定义。

这是后来整个 typing 生态的地基。


三、类型提示正式诞生(PEP 484, Python 3.5,2015)

真正现代类型系统开始:

PEP 484

引入:

from typing import List

def greet(names: List[str]) -> None:
    ...

同时诞生:

  • typing 模块
  • TypeVar
  • Generic
  • Union
  • Optional
T = TypeVar("T")

def first(items: list[T]) -> T:
    return items[0]

重要意义

第一次:

  • 类型可以被静态检查(如 mypy)
  • IDE 能做推断
  • Python 开始有“渐进类型系统”(Gradual Typing)

这是革命性阶段。


四、typing 爆炸增长时期(2015–2019)

这个阶段像寒武纪爆发。


PEP 526 — 变量注解

age: int = 18

以前:

age = 18  # type: int

终于不用 type comment。


PEP 544 — Protocol(结构化类型)

PEP 544

从 Nominal Typing:

class Bird:
    def fly(self): ...

变成 Duck Typing 的静态版:

from typing import Protocol

class Flyable(Protocol):
    def fly(self) -> None:
        ...

这是非常 Pythonic 的进化。


TypedDict

from typing import TypedDict

class User(TypedDict):
    name: str
    age: int

让 dict 也有结构类型。


五、语法现代化(Python 3.9–3.10)

这是“去 typing 冗余化”阶段。


PEP 585 — 内置泛型

PEP 585

以前:

from typing import List, Dict

x: List[str]

现在:

x: list[str]

巨大简化。


PEP 604 — | 联合类型

PEP 604

以前:

Optional[str]
Union[int, str]

现在:

str | None
int | str

几乎像现代语言:

  • TypeScript
  • Kotlin
  • Rust 风格

PEP 563 / postponed evaluation

解决前向引用:

class Node:
    parent: Node

以前必须:

parent: "Node"

六、高级类型系统时代(3.10–3.12)

开始变得“像真正编译型语言”。


ParamSpec

高阶函数类型:

from typing import ParamSpec

P = ParamSpec("P")

装饰器终于能正确表达:

def decorator(fn: Callable[P, T]) -> Callable[P, T]:

TypeGuard

类型缩窄:

def is_str(x: object) -> TypeGuard[str]:

类似 TypeScript narrowing。


Self(PEP 673)

class Builder:
    def set(self) -> Self:
        return self

终于不用:

T = TypeVar("T", bound="Builder")

七、PEP 695:泛型语法革命(Python 3.12)

大事件。

PEP 695

旧写法:

T = TypeVar("T")

def identity(x: T) -> T:
    return x

新写法:

def identity[T](x: T) -> T:
    return x

类:

class Box[T]:
    ...

终于接近:

  • C++
  • Rust
  • TypeScript

很多人认为这是 typing 2.0。


八、运行时类型时代(Pydantic 等生态)

静态类型开始影响运行时。

典型:

Pydantic

class User(BaseModel):
    name: str
    age: int

类型不只是给 checker:

  • 校验
  • 序列化
  • API schema
  • ORM

尤其和 FastAPI 一起,把 type hints 推到主流。


演化主线可以总结成四代

时代 特征
Docstring时代 文档化类型
PEP484时代 渐进静态类型
现代typing时代 Protocol / 泛型增强
PEP695+时代 接近完整类型系统
posted @ 2026-04-22 23:56  悠哉大斌  阅读(38)  评论(0)    收藏  举报