2026-06-25 06:50:43
在Python中,元类(metaclass)是用于创建类的类,通过控制类的创建行为实现类的定制化。其核心机制是通过继承type类并重写__new__方法,在类创建时动态修改类的属性或结构。
一、元类基础概念元类的作用
元类是类的“模板”,用于控制类的创建过程。
常规类通过class定义,而元类通过type或自定义元类派生。
实例由类创建,类由元类创建,形成“元类 → 类 → 实例”的层级关系。
type()函数与动态创建类
type()既是检查对象类型的工具,也是动态创建类的核心函数。
动态创建类的语法:
MyClass = type('MyClass', (父类,), {'属性名': 值})示例:
def fn(self): print("Hello")Hello = type('Hello', (), {'hello': fn}) # 动态创建类h = Hello()h.hello() # 输出: Hello基本结构
自定义元类需继承type,并重写__new__方法(控制类的创建)或__init__方法(初始化类)。
__new__参数:
cls:当前元类
name:类名
bases:父类元组
attrs:类属性字典
示例:为列表添加add方法
class ListMetaclass(type): def __new__(cls, name, bases, attrs): attrs['add'] = lambda self, value: self.append(value) # 动态添加方法 return type.__new__(cls, name, bases, attrs)class MyList(list, metaclass=ListMetaclass): # Python 3语法 passL = MyList()L.add(1) # 输出: [1]ORM框架的核心需求
将数据库表映射为Python类,表字段映射为类属性。
动态生成SQL语句(如INSERT、SELECT)。
实现步骤
定义字段基类:
class Field(object): def __init__(self, name, column_type): self.name = name self.column_type = column_typeclass StringField(Field): def __init__(self, name): super().__init__(name, 'varchar(100)')自定义元类:
class ModelMetaclass(type): def __new__(cls, name, bases, attrs): if name == 'Model': # 跳过基类Model的修改 return type.__new__(cls, name, bases, attrs) mappings = {} for k, v in attrs.items(): if isinstance(v, Field): mappings[k] = v attrs.pop(k) # 移除类属性,避免冲突 attrs['__table__'] = name # 表名默认为类名 attrs['__mappings__'] = mappings # 保存字段映射 return type.__new__(cls, name, bases, attrs)定义基类Model:
class Model(dict, metaclass=ModelMetaclass): def __getattr__(self, key): try: return self[key] except KeyError: raise AttributeError(f"'Model' object has no attribute '{key}'") def save(self): fields = [] params = [] args = [] for k, v in self.__mappings__.items(): fields.append(v.name) params.append('?') args.append(getattr(self, k)) sql = f'INSERT INTO {self.__table__} ({",".join(fields)}) VALUES ({",".join(params)})' print(f'SQL: {sql}nARGS: {args}') # 实际场景中需执行SQL使用示例
class User(Model): id = IntegerField('id') name = StringField('username') email = StringField('email')u = User(id=123, name='Alice', email='alice@example.com')u.save()# 输出:# SQL: INSERT INTO User (id,username,email) VALUES (?,?,?)# ARGS: [123, 'Alice', 'alice@example.com']继承与元类冲突
子类会隐式继承父类的元类。若父类指定元类A,子类需显式声明metaclass=A或使用兼容的元类。
性能影响
元类在类创建时执行,频繁动态修改可能影响性能,需谨慎使用。
替代方案
简单场景可用装饰器或__init_subclass__(Python 3.6+)替代元类。
完整代码参考: