元类是类创建前的底层补丁,仅当需统一修改属性、方法、继承或验证结构时才使用,常见于框架开发;__init_subclass__可替代大部分场景,更轻量易调试。
元类不是用来“炫技”的,它是在常规类机制无法满足需求时的底层补丁——绝大多数项目根本用不到,强行使用反而增加维护成本。
type 或自定义元类?只有当你要在类创建完成前,统一修改其属性、方法、继承关系或验证结构时,才

Model 类、SQLModel 的声明式模型)或强约束的 SDK。
__new__ 中操作 namespace 并修改 cls.__name__ 后调用 super().__new__
schema 属性且类型为 dict?在元类的 __new__ 里检查 namespace.get('schema'),不合法就抛 TypeError
_handler_ 开头的方法自动收集为事件处理器?在 __new__ 阶段扫描 namespace,提取后注入类属性__init_subclass__ 能替代大部分元类场景Python 3.6+ 引入的 __init_subclass__ 是更轻量、更易读的替代方案,适用于大多数“子类初始化时做点事”的需求,比如自动注册、参数校验、默认属性注入。
__mro__
__new__
class Plugin:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if not hasattr(cls, 'name'):
raise ValueError(f'{cls.__name__} must define "name"')
registry[cls.name] = clsmetaclass=type 不等于“没用元类”?所有类默认都由 type 构建,显式写 metaclass=type 只是强调“我清楚自己在用内置元类”,但它不会改变行为——除非你继承 type 并重写 __new__ 或 __init__。
metaclass=type 就能控制类创建” → 实际上什么也没覆盖type,例如:class AutoRegister(type):
def __new__(mcs, name, bases, namespace):
cls = super().__new__(mcs, name, bases, namespace)
registry[name] = cls
return cls__new__ 接收的是“将要创建的类”的参数,不是实例参数;返回值必须是类对象,否则会报 TypeError: metaclass __new__() should return a class
元类真正的复杂点不在语法,而在调试链路:类定义 → 元类 __new__ → 元类 __init__ → 类的 __new__ → 类的 __init__。一旦出错,堆栈里混着多层元信息,而 __init_subclass__ 至少把逻辑压平了一层。