# Python 元类

## 学习目标
- 理解元类的概念和作用
- 掌握 `type()` 动态创建类
- 学会自定义元类
- 了解元类的应用场景

---

## 一、类也是对象

在 Python 中，**一切皆对象**，类本身也是对象。类是 `type` 的实例。

```python
class MyClass:
    pass

# 类是对象
print(type(MyClass))       # <class 'type'>
print(type(int))           # <class 'type'>
print(type(str))           # <class 'type'>

# 对象是类的实例
obj = MyClass()
print(type(obj))           # <class '__main__.MyClass'>

# 所有类都继承自 object
print(issubclass(MyClass, object))   # True
print(issubclass(int, object))       # True
```

---

## 二、type() 动态创建类

`type()` 不仅可以查看类型，还可以用来动态创建类。

### 2.1 基本语法

```python
# type(name, bases, namespace)
# name: 类名
# bases: 父类元组
# namespace: 属性和方法字典

# 等价于 class MyClass: pass
MyClass = type("MyClass", (), {})
obj = MyClass()
print(type(obj))           # <class '__main__.MyClass'>

# 等价于：
# class Dog:
#     species = "Canis familiaris"
#     def bark(self):
#         return "汪汪!"

Dog = type("Dog", (), {
    "species": "Canis familiaris",
    "bark": lambda self: "汪汪!"
})

dog = Dog()
print(dog.species)         # Canis familiaris
print(dog.bark())          # 汪汪!
```

### 2.2 带继承和方法

```python
def say_hello(self):
    return f"Hello, I'm {self.name}"

# 创建 Animal 基类
Animal = type("Animal", (), {
    "__init__": lambda self, name: setattr(self, "name", name),
    "speak": lambda self: "动物发出声音",
})

# 创建 Dog 子类
Dog = type("Dog", (Animal,), {
    "speak": lambda self: f"{self.name} 说: 汪汪!",
})

dog = Dog("Buddy")
print(dog.speak())         # Buddy 说: 汪汪!
```

---

## 三、自定义元类

元类是创建类的"类"。自定义元类需要继承 `type`。

### 3.1 基本元类

```python
class Meta(type):
    """自定义元类"""

    def __new__(mcs, name, bases, namespace):
        """创建类时调用"""
        print(f"创建类: {name}")
        print(f"  父类: {bases}")
        print(f"  命名空间: {list(namespace.keys())}")

        # 可以修改命名空间
        namespace["created_by"] = "Meta"

        # 调用父类的 __new__ 创建类
        return super().__new__(mcs, name, bases, namespace)

    def __init__(cls, name, bases, namespace):
        """初始化类时调用"""
        print(f"初始化类: {name}")
        super().__init__(name, bases, namespace)

    def __call__(cls, *args, **kwargs):
        """创建实例时调用"""
        print(f"创建 {cls.__name__} 的实例")
        return super().__call__(*args, **kwargs)


class MyClass(metaclass=Meta):
    class_attr = 100

    def __init__(self, value):
        self.value = value


# 输出：
# 创建类: MyClass
#   父类: ()
#   命名空间: ['__module__', '__qualname__', 'class_attr', '__init__', 'created_by']
# 初始化类: MyClass

obj = MyClass(42)
# 输出：创建 MyClass 的实例

print(obj.value)           # 42
print(MyClass.created_by)  # Meta
```

### 3.2 自动注册子类

```python
class PluginMeta(type):
    """自动注册插件的元类"""
    registry = {}

    def __new__(mcs, name, bases, namespace):
        cls = super().__new__(mcs, name, bases, namespace)
        if name != "BasePlugin":   # 不注册基类
            mcs.registry[name] = cls
            print(f"注册插件: {name}")
        return cls


class BasePlugin(metaclass=PluginMeta):
    """插件基类"""
    def execute(self):
        raise NotImplementedError


class EmailPlugin(BasePlugin):
    def execute(self):
        return "发送邮件"


class SMSPlugin(BasePlugin):
    def execute(self):
        return "发送短信"


class PushPlugin(BasePlugin):
    def execute(self):
        return "推送通知"


# 查看注册的所有插件
print("\n已注册插件:")
for name, cls in PluginMeta.registry.items():
    print(f"  {name}: {cls}")

# 动态创建插件实例
plugin_name = "EmailPlugin"
if plugin_name in PluginMeta.registry:
    plugin = PluginMeta.registry[plugin_name]()
    print(f"\n执行 {plugin_name}: {plugin.execute()}")
```

---

## 四、元类的应用场景

### 4.1 属性名强制小写

```python
class LowerCaseMeta(type):
    """将类中所有属性名转为小写"""

    def __new__(mcs, name, bases, namespace):
        # 创建新的命名空间，属性名转为小写
        lower_namespace = {}
        for key, value in namespace.items():
            if not key.startswith("__"):
                lower_namespace[key.lower()] = value
            else:
                lower_namespace[key] = value

        return super().__new__(mcs, name, bases, lower_namespace)


class MyClass(metaclass=LowerCaseMeta):
    Name = "Alice"
    AGE = 25
    CITY = "Beijing"

    def SayHello(self):
        return f"Hello, {self.name}"


obj = MyClass()
print(obj.name)            # Alice
print(obj.age)             # 25
print(obj.city)            # Beijing
print(obj.sayhello())      # Hello, Alice
```

### 4.2 单例模式

```python
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(f"创建数据库连接: {connection_string}")


db1 = Database("mysql://localhost/mydb")
db2 = Database("mysql://localhost/other")

print(db1 is db2)          # True（同一个实例）
print(db1.connection_string)   # mysql://localhost/mydb
print(db2.connection_string)   # mysql://localhost/mydb
```

### 4.3 ORM 字段自动收集

```python
class Field:
    def __init__(self, field_type="TEXT", default=None):
        self.field_type = field_type
        self.default = default

    def __repr__(self):
        return f"Field({self.field_type})"


class ModelMeta(type):
    """ORM 元类：自动收集字段"""

    def __new__(mcs, name, bases, namespace):
        # 收集 Field 类型的属性
        fields = {}
        for key, value in namespace.items():
            if isinstance(value, Field):
                fields[key] = value

        # 添加 fields 属性
        namespace["_fields"] = fields

        cls = super().__new__(mcs, name, bases, namespace)

        # 如果有表名设置
        if "__tablename__" not in namespace:
            cls.__tablename__ = name.lower()

        return cls

    def __repr__(cls):
        fields = ", ".join(f"{k}={v}" for k, v in cls._fields.items())
        return f"<Model {cls.__name__}({fields})>"


class Model(metaclass=ModelMeta):
    pass


class User(Model):
    __tablename__ = "users"
    id = Field("INTEGER", default=0)
    name = Field("TEXT", default="")
    email = Field("TEXT", default="")


class Post(Model):
    id = Field("INTEGER")
    title = Field("TEXT")
    content = Field("TEXT")


print(User)
# <Model User(id=Field(INTEGER), name=Field(TEXT), email=Field(TEXT))>

print(Post)
# <Model Post(id=Field(INTEGER), title=Field(TEXT), content=Field(TEXT))>

print(User.__tablename__)  # users
print(Post.__tablename__)  # post（自动小写）
```

---

## 五、元类 vs 类装饰器

元类和类装饰器都可以修改类的行为，但适用场景不同。

```python
# 类装饰器（更简单）
def singleton(cls):
    """单例装饰器"""
    instance = {}
    def wrapper(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]
    return wrapper


@singleton
class Logger:
    def __init__(self):
        print("创建 Logger")


# 元类（更强大，可以控制类创建过程）
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 Config(metaclass=SingletonMeta):
    def __init__(self):
        print("创建 Config")


# 选择建议：
# - 简单修改类：使用类装饰器
# - 深度定制类创建过程：使用元类
# - 框架开发：使用元类
```

---

## 六、综合示例

```python
"""
接口检查元类：确保子类实现了所有抽象方法
"""

from abc import abstractmethod


class InterfaceMeta(type):
    """检查接口实现的元类"""

    def __new__(mcs, name, bases, namespace):
        cls = super().__new__(mcs, name, bases, namespace)

        # 跳过抽象基类本身
        if getattr(cls, "__abstract__", False):
            return cls

        # 检查所有抽象方法是否已实现
        for base in bases:
            for attr_name in dir(base):
                attr = getattr(base, attr_name)
                if getattr(attr, "__isabstractmethod__", False):
                    if attr_name not in namespace:
                        raise TypeError(
                            f"类 {name} 必须实现抽象方法 '{attr_name}'"
                        )

        return cls


class BaseHandler(metaclass=InterfaceMeta):
    """处理器基类"""
    __abstract__ = True

    @abstractmethod
    def handle(self, request):
        """处理请求"""
        pass

    @abstractmethod
    def validate(self, request):
        """验证请求"""
        pass


# 正确实现
class HTTPHandler(BaseHandler):
    def handle(self, request):
        return f"处理 HTTP 请求: {request}"

    def validate(self, request):
        return True


# 错误实现（会报错）
# class BrokenHandler(BaseHandler):
#     def handle(self, request):
#         pass
#     # 缺少 validate 方法！


handler = HTTPHandler()
print(handler.handle("GET /api/users"))
```

---

## 小结

- 类是 `type` 的实例，`type` 是所有类的默认元类
- `type(name, bases, namespace)` 可以动态创建类
- 自定义元类继承 `type`，重写 `__new__` 和 `__init__`
- 元类应用场景：ORM、单例、接口检查、自动注册、属性转换等
- 类装饰器是元类的轻量级替代方案
- 大多数情况不需要元类，过度使用会增加代码复杂度

---

## 练习

1. 使用 `type()` 动态创建一个 `Calculator` 类，包含 `add` 和 `subtract` 方法。
2. 编写一个元类，自动为类中所有方法添加计时功能。
3. 实现一个元类，要求所有属性名必须以小写字母开头，否则抛出异常。
4. 对比类装饰器和元类实现单例模式，分析各自的优缺点。
5. 使用元类实现一个简单的 ORM，支持定义表名和字段类型。

