← [ BACK_TO_NOTES ]

Python 元类概览

元类控制类的创建,通常为 type 或其子类;区分元类、子类钩子与类装饰器的职责。

#concept #growing #dev #python #python

[!info] related notes

Python 元类概览

这个概念为什么出现

ORM、API 框架有时在类定义时收集字段、注册模型。这是元类或类装饰器/ __init_subclass__ 的领域。滥用元类会让代码难读。

[!abstract] 一句话理解 类是对象,其类型默认是 type;自定义元类可拦截类创建,但优先考虑 __init_subclass__ 与类装饰器。

最小可运行示例

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

场景:插件子类自动注册(用 init_subclass)

# plugin_registry_demo.py
# 业务意图:子类定义时自动注册,无需元类。
# 教学点:多数注册需求不必元类。

class Plugin:
    registry: dict[str, type] = {}

    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        Plugin.registry[cls.__name__] = cls


class ExportCsv(Plugin):
    pass


class ExportJson(Plugin):
    pass


def main() -> None:
    print(sorted(Plugin.registry))


if __name__ == "__main__":
    main()

建议运行:

python plugin_registry_demo.py

期望输出:

['ExportCsv', 'ExportJson']

结合场景再看三个关注点

  1. 只有执行到类定义才注册;本例不会自动发现未导入插件,并会按类名覆盖同名条目。注册键和冲突策略需另定。
  2. __init_subclass__ 比元类更易组合。
  3. 真要元类,先读框架文档。

核心概念与准确模型

  • type(name, bases, namespace) 是简单动态造类的近似;class 语句还涉及元类选择、prepare 与类体执行等步骤。
  • 常见自定义元类继承 type;metaclass 参数也可指定其他可调用对象,不能把子类关系当成全部形式。
  • 使用类型元类时,选定的元类须为各候选元类的子类型;没有兼容候选会抛 TypeError,不会自动合并冲突。

边界情况与反直觉行为

  1. 多重元类冲突
  2. 在通常的 type 创建流程中,init_subclass 在类装饰器应用之前调用;装饰器若返回替代对象,本例注册表仍持有原类。
  3. 调试栈难读

常见误区

[!warning] 常见误区:学会元类就要用 错误理解:高级=更好。
正确模型:最后手段;优先子类钩子与装饰器。

工程实践

  • 业务代码避免自定义元类
  • 库作者写清约束
  • 测试注册表隔离

本节总结

元类强大且危险。理解它为了读框架,而不是到处造轮。

自测题

  1. 类的默认元类?
  2. 注册插件优先 API?
参考答案
  1. type。
  2. __init_subclass__ 或类装饰器。

延伸阅读与资料来源

资料类型支撑内容
Metaclasses规范数据模型
init_subclass规范子类钩子
创建于 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
关闭浮层 / 取消命令;输入框内清空文本