元类是创建类的类,普通类创建实例;type是python默认元类,类的__class__指向其元类,元类需继承type且在类定义结束时执行。

什么是元类?它和普通类有什么区别?
元类是“创建类的类”。普通类用来创建实例(对象),而元类用来创建类本身。Python 中,type 是默认的元类:当你写 class A: pass,解释器实际调用 type('A', (), {}) 来构造类对象。
关键区别:
- 类的
__class__指向它的元类(如A.__class__是type) - 元类必须继承自
type或另一个元类 - 元类在类定义结束时自动执行,可用于拦截、修改类的构建过程
如何自定义元类?常用场景有哪些?
通过定义一个继承自 type 的类,并重写 __new__ 或 __init__ 方法实现。典型写法:
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class A(metaclass=SingletonMeta):
pass
高频使用场景包括:
立即学习“Python免费学习笔记(深入)”;
- 单例模式:控制类只被实例化一次(如上例)
-
自动注册子类:在
__new__中将新类加入全局 registry -
字段校验/注入:检查类中是否定义了必需属性,或自动添加
__slots__、日志方法等 - ORM 映射:Django 和 SQLAlchemy 内部用元类解析模型字段并绑定数据库元信息
metaclass 和 __new__、__init__ 的执行顺序是怎样的?
当定义一个类时,执行顺序严格为:
- 元类的
__new__(创建类对象) - 元类的
__init__(初始化类对象) - 元类的
__call__(当类被调用实例化时触发,常用于单例等逻辑) - 类自身的
__new__(创建实例) - 类自身的
__init__(初始化实例)
注意:__new__ 和 __init__ 在元类中作用于“类”,不是“实例”;它们接收的第一个参数是 cls(即要创建的类),而非实例。
有没有更轻量的替代方案?什么时候该避免用元类?
大多数元类能做的事,可以用以下方式更清晰地实现:
- 类装饰器:对类做后置处理,语法简洁,调试友好
- __init_subclass__(Python 3.6+):在子类定义时自动触发,适合简单钩子逻辑(如注册、验证)
- 描述符 + __set_name__:管理属性行为,无需侵入类构建流程
应避免使用元类的情况:
- 逻辑可以用组合、装饰器或基类方法替代
- 团队不熟悉元类,会显著增加维护成本
- 只是为了“炫技”或过早优化
元类是强大但隐晦的工具,真正需要它的地方很少——多数时候,它是在框架底层默默工作的那部分,而不是业务代码的首选。









