元类是控制类创建过程的钩子,非高级建类方式;type()最简单直接,适用于临时动态建类,如MyClass = type('MyClass', (object,), {'x': 1, 'show': lambda self: print(self.x)})。

元类不是创建类的“高级方式”,而是控制类创建过程的钩子;直接用 type() 动态造类最简单,但想统一干预所有子类行为(比如自动注册、字段校验、API 路由绑定),才需要自定义元类。
什么时候该用 type() 而不是写元类?
绝大多数动态建类需求,type() 就够了——它就是 Python 内部创建类时调用的底层函数。
- 你只需要临时生成一个类,不涉及继承链统一改造:直接用
type(name, bases, namespace) -
name是字符串类名,bases是父类元组(如(object,)),namespace是属性字典(可含方法) - 常见错误:把方法写成普通函数却没绑定到
namespace,结果实例调用时报AttributeError - 示例:
MyClass = type('MyClass', (object,), {'x': 1, 'show': lambda self: print(self.x)})
自定义元类必须重写 __new__ 还是 __init__?
优先重写 __new__:它在类对象诞生前介入,能修改类名、父类、属性字典;__init__ 只能操作已存在的类对象,改不了继承关系或核心结构。
-
__new__(cls, name, bases, namespace, **kwargs)的四个固定参数不能少,哪怕不用**kwargs - 必须返回一个类对象(通常是
super().__new__(cls, name, bases, namespace)),否则类定义会失败 - 别在
__new__里对namespace做原地修改(如namespace['x'] = ...),某些 Python 版本下可能被忽略;应构造新字典再传给父类 - 如果只是想打日志或触发注册,
__init__更安全,因为它不干涉类构建逻辑
元类中访问类的注解(__annotations__)为什么是空的?
因为 __annotations__ 默认在类体执行完、__new__ 返回后才被注入到类对象上——此时元类的 __new__ 和 __init__ 都已执行完毕。
立即学习“Python免费学习笔记(深入)”;
- 想提前读类型注解,得手动解析
namespace中的字符串(如def f(x: int): pass的注解不在里面) - 更可靠的做法:在元类
__init__之后,通过cls.__annotations__访问(此时已存在),但注意这要求用户代码用了 Python 3.6+ 的变量注解语法 - 若依赖注解做字段校验,建议搭配
dataclasses或pydantic,它们内部已处理好时机问题,比手写元类稳得多
元类真正的难点不在语法,而在调试:一旦出错,报错堆栈往往指向类定义行而非元类内部,且 IDE 几乎不提供跳转支持。先用 type() 验证逻辑,再平移进元类,能避开大部分隐形坑。


















