Python 中的元类(Metaclass)是什么?

元类是"类的类"——控制类如何被创建。继承 type 定义元类,通过 __new__/__init__ 在类创建时干预。典型用途:单例、注册表、ORM。本文用例子讲清楚。

最佳实践
Python 中的元类(Metaclass)是什么?封面

元类是创建类的"模板":普通类创造实例,元类创造类。Python 中 type 就是默认元类——你写的每个类都是 type 的实例。自定义元类可以在类被创建时修改它(添加方法、注册、强制规则)。

一个例子:单例元类

class Singleton(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 Logger(metaclass=Singleton):
    pass

a = Logger()
b = Logger()
print(a is b)  # True——永远只有一个实例

Logger(...) 调用的是元类的 __call__,在这里拦截实现实例缓存。

元类的钩子

class MyMeta(type):
    def __new__(mcs, name, bases, attrs):
        # 类创建时:可以修改属性、添加方法
        attrs['version'] = '1.0'
        return super().__new__(mcs, name, bases, attrs)

    def __init__(cls, name, bases, attrs):
        # 类创建后:注册、校验
        super().__init__(name, bases, attrs)

实际用途

  • ORM:Django/SQLAlchemy 用元类把类属性(Field)转成表结构定义;
  • 插件注册:类创建时自动加入注册表;
  • 单例:如上例;
  • 接口强制:检查子类必须实现某些方法(ABC 的底层机制)。

什么时候不要用

Tim Peters 名言:"元类是更深层次的魔法,99% 的用户永远不需要考虑它。"大多数需求用装饰器、类装饰器、__init_subclass__ 就能实现,更简单:

# 多数"注册子类"的需求用 __init_subclass__ 就够
class Plugin:
    registry = []
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        Plugin.registry.append(cls)

常见问题(FAQ)

Q:元类和继承有什么区别?
A:继承定义"类与类"的 is-a 关系;元类定义"类怎么被造出来"。正交的两个概念。

Q:type 到底是什么?
A:type 既是类型检查函数,又是所有类的元类。type(MyClass) 返回 typetype(type) 也返回 type(自举)。

Q:面试外的日常开发需要懂吗?
A:理解概念即可。日常写业务代码几乎用不到自定义元类,但读懂框架源码(Django models)需要这个知识。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台