Python 元类概览
元类是 type 的子类,控制类的创建;大多数业务代码不需要自定义元类。
#type / concept
#status / growing
#tech / dev
#resource / python
#tech / lang / python
[!info] 关联笔记
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']
结合场景再看三个关注点
- 类创建时副作用可注册插件。
__init_subclass__比元类更易组合。- 真要元类,先读框架文档。
核心概念与准确模型
class A: ...≈type('A', bases, namespace)- 元类继承
type并实现__new__/__init__ - 元类冲突要可计算合并
边界情况与反直觉行为
- 多重元类冲突
- 与装饰器顺序
- 调试栈难读
常见误区
[!warning] 常见误区:学会元类就要用 错误理解:高级=更好。
正确模型:最后手段;优先子类钩子与装饰器。
工程实践
- 业务代码避免自定义元类
- 库作者写清约束
- 测试注册表隔离
本节总结
元类强大且危险。理解它为了读框架,而不是到处造轮。
自测题
- 类的默认元类?
- 注册插件优先 API?
参考答案
type。__init_subclass__或类装饰器。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Metaclasses | 规范 | 数据模型 |
| init_subclass | 规范 | 子类钩子 |