第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__` 简化子类注册
五、思考与练习
什么时候应该用元类而非类装饰器?
如何实现一个自动序列化的元类?