← [ BACK_TO_NOTES ]

Python Protocol 与结构化类型

Protocol 在类型检查层表达结构要求,实现静态鸭子类型,与运行时鸭子类型互补。

#concept #growing #dev #python #python

[!info] related notes

Python Protocol 与结构化类型

这个概念为什么出现

运行时鸭子类型灵活,但公共库希望在 CI 就发现“少了 close 方法”。typing.Protocol 让类型检查器按结构判定兼容,无需名义继承。

[!abstract] 一句话理解 Protocol 定义一组必须具备的方法/属性;类型检查器对结构匹配的类型放行,即使它们未显式继承该 Protocol。

最小可运行示例

先把示例放进业务场景,再看代码:

场景:关闭资源的统一收尾函数

# protocol_closer.py
# 业务意图:close_all 接受任何带 close() 的对象。
# 教学点:
# - Protocol 定义结构;
# - 不同类结构兼容;
# - runtime_checkable 也不要求实现类继承 Protocol。

from collections.abc import Iterable
from typing import Protocol


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


class DbConn:
    def close(self) -> None:
        print("db closed")


class FileHandle:
    def close(self) -> None:
        print("file closed")


def close_all(resources: Iterable[Closable]) -> None:
    for r in resources:
        r.close()


def main() -> None:
    close_all([DbConn(), FileHandle()])


if __name__ == "__main__":
    main()

建议运行:

python protocol_closer.py

期望输出:

db closed
file closed

结合场景再看三个关注点

  1. DbConn/FileHandle 无共同基类仍可协作。
  2. 静态检查器检查方法签名/属性类型是否兼容,不能只看名字;Any 或未检查的动态代码仍可能绕过它。这里只迭代,用 Iterable 比可变 list 更贴合契约。
  3. @runtime_checkable 允许有限的 isinstance 检查,也不要求显式继承;它不验证完整签名、返回类型或关闭行为。

核心概念与准确模型

  • 结构子类型 vs 名义子类型
  • 方法体可用 … 声明签名,也可给默认实现;隐式结构兼容的类不会继承该默认实现。
  • 可泛型 Protocol
  • 与 ABC 虚拟子类不同层

边界情况与反直觉行为

  1. 静态结构匹配包含类型兼容性,但不证明业务语义。本例任一 close 抛异常就停止,后续资源不再关闭;需要全量清理时应另定异常收集/退出协议。
  2. runtime_checkable 只查存在性,不查签名细节。
  3. 回调协议用 Callable 有时更简单。

常见误区

[!warning] 常见误区:Protocol 会改变运行时继承 错误理解:必须 subclass Protocol。
正确模型:默认是静态契约;运行时对象无需知道 Protocol。

工程实践

  • 公共插件点用 Protocol 文档化
  • 与 pyright 严格模式配合
  • 小而稳的协议优于大而全

本节总结

Protocol 把鸭子类型提升到可检查的工程实践,不牺牲组合灵活性。

自测题

  1. Protocol 与 ABC 强制继承差别?
  2. 为什么还要测试?
参考答案
  1. Protocol 结构兼容即可;ABC 常要名义注册/继承。
  2. 结构匹配不等于业务语义正确。

延伸阅读与资料来源

资料类型支撑内容
Protocol文档API
PEP 544PEPProtocols
创建于 2026/7/15 更新于 2026/10/6
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本