目录

第十六章:元类

本章目标

完成本章学习后,你将能够:

什么是元类

元类(Metaclass)是“类的类”。类定义对象的行为,元类定义类的行为。

# 一切都是对象,包括类
class MyClass:
    pass
 
obj = MyClass()
print(type(obj))     # <class '__main__.MyClass'>
print(type(MyClass)) # <class 'type'>
 
# type就是Python的默认元类

使用type创建类

# 传统方式
class MyClass:
    x = 1
    def greet(self):
        return "Hello"
 
# 使用type创建
MyClass = type('MyClass', (), {
    'x': 1,
    'greet': lambda self: "Hello"
})
 
# 参数:类名,基类元组,属性字典

自定义元类

class Meta(type):
    """自定义元类"""
 
    def __new__(mcs, name, bases, namespace, **kwargs):
        """创建类时调用"""
        print(f"Creating class {name}")
        # 可以修改namespace
        namespace['created_by'] = 'Meta'
        return super().__new__(mcs, name, bases, namespace)
 
    def __init__(cls, name, bases, namespace, **kwargs):
        """初始化类时调用"""
        print(f"Initializing class {name}")
        super().__init__(name, bases, namespace)
 
    def __call__(cls, *args, **kwargs):
        """实例化时调用"""
        print(f"Creating instance of {cls.__name__}")
        return super().__call__(*args, **kwargs)
 
class MyClass(metaclass=Meta):
    def __init__(self, value):
        self.value = value
 
# 使用
obj = MyClass(42)

元类应用:单例模式

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 Database(metaclass=SingletonMeta):
    def __init__(self, connection_string):
        self.connection_string = connection_string
        print("Database initialized")
 
db1 = Database("postgresql://localhost")
db2 = Database("mysql://localhost")
print(db1 is db2)  # True

元类应用:ORM

class Field:
    """字段描述符"""
    def __init__(self, name, field_type):
        self.name = name
        self.field_type = field_type
 
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__.get(self.name)
 
    def __set__(self, instance, value):
        instance.__dict__[self.name] = value
 
class ModelMeta(type):
    """ORM元类"""
 
    def __new__(mcs, name, bases, namespace):
        if name == 'Model':
            return super().__new__(mcs, name, bases, namespace)
 
        # 收集字段
        fields = {}
        for key, value in list(namespace.items()):
            if isinstance(value, Field):
                fields[key] = value
 
        namespace['_fields'] = fields
        namespace['_table_name'] = name.lower()
 
        return super().__new__(mcs, name, bases, namespace)
 
class Model(metaclass=ModelMeta):
    """ORM基类"""
 
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
 
    def save(self):
        fields = ', '.join(self._fields.keys())
        values = ', '.join(str(getattr(self, k)) for k in self._fields)
        print(f"INSERT INTO {self._table_name} ({fields}) VALUES ({values})")
 
class User(Model):
    name = Field('name', str)
    age = Field('age', int)
    email = Field('email', str)
 
# 使用
user = User(name="Alice", age=25, email="alice@example.com")
user.save()

本章练习

1. 实现单例元类 2. 创建注册元类,自动注册所有子类 3. 实现抽象方法检查元类 4. 创建自动属性生成元类

下一章:第十七章:设计模式