6Fluent Python(第2版)

元编程

元类与类工厂

元类类装饰器描述符协议__init_subclass__

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第6章:元编程

一、导读

1.1 本章学习目标

第6章讲解 Python 的元编程:元类、类装饰器、__init_subclass__。

本章核心学习目标:

  • 掌握元类:用元类控制类的创建
  • 理解类装饰器:修改类的行为
  • 掌握 `__init_subclass__`:子类注册机制

1.2 为什么本章如此重要

元编程是构建框架和库的高级工具。ORM、序列化框架、插件系统等都依赖元编程。

1.3 核心问题引导

元类是什么?type 和 object 的关系是什么?

类装饰器和元类有什么区别?

__init_subclass__ 如何简化子类注册?


二、核心概念详解

2.1 元类

python
# 类是 type 的实例
class MyClass:
    pass

print(type(MyClass))  # <class 'type'>
print(type(type))     # <class 'type'>

# 元类: 控制类的创建
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.conn = connection_string

db1 = Database("sqlite:///test.db")
db2 = Database("sqlite:///other.db")
print(db1 is db2)  # True (单例)

2.2 类装饰器

python
def add_repr(cls):
    """自动为类添加 __repr__"""
    def __repr__(self):
        attrs = ', '.join(f'{k}={v!r}' for k, v in self.__dict__.items())
        return f'{cls.__name__}({attrs})'
    cls.__repr__ = __repr__
    return cls

@add_repr
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

p = Point(1, 2)
print(p)  # Point(x=1, y=2)

2.3 __init_subclass__

python
class PluginBase:
    _plugins = {}
    
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        # 自动注册子类
        PluginBase._plugins[cls.__name__] = cls
    
    @classmethod
    def get_plugin(cls, name):
        return cls._plugins[name]

class JSONPlugin(PluginBase):
    def serialize(self, data):
        import json
        return json.dumps(data)

class YAMLPlugin(PluginBase):
    def serialize(self, data):
        import yaml
        return yaml.dump(data)

# 子类自动注册
print(PluginBase.get_plugin('JSONPlugin'))  # <class 'JSONPlugin'>

三、实战案例

3.1 案例一:自动验证的元类

python
class ValidationMeta(type):
    def __new__(mcs, name, bases, namespace):
        # 收集所有带 __expected_type__ 的属性
        validators = {}
        for key, value in namespace.items():
            if hasattr(value, '__expected_type__'):
                validators[key] = value.__expected_type__
        
        # 创建类
        cls = super().__new__(mcs, name, bases, namespace)
        cls._validators = validators
        
        # 包装 __init__
        original_init = cls.__init__
        def validated_init(self, *args, **kwargs):
            original_init(self, *args, **kwargs)
            for attr, expected_type in self._validators.items():
                value = getattr(self, attr, None)
                if value is not None and not isinstance(value, expected_type):
                    raise TypeError(f"{attr} must be {expected_type.__name__}")
        
        cls.__init__ = validated_init
        return cls

class Validated(metaclass=ValidationMeta):
    pass

四、本章小结

元类控制类的创建过程

类装饰器修改类的行为

`__init_subclass__` 简化子类注册


五、思考与练习

什么时候应该用元类而非类装饰器?

如何实现一个自动序列化的元类?


6/8元编程
0%