元类
1、元类(Metaclass)的概念
- 元类是Python中一个高级概念,本质上是**“类的类”**,用于控制创建类的过程。元类是创建类的模板
- 在Python中:
- 类定义了实例的行为
- 元类定义了类的行为
2、python中的默认元类
-
在Python中,type是所有类的默认元类。
-
我们所熟知的object基类就是type元类的一个实例
-
当使用class关键字创建类时,因为没有指定元类,因此python会寻找父类的元类,如果父类也没有元类的话会退回到最初的type类。
-
找到元类后,基于元类创建类其实就是执行了元类中的
__new__
和__init__
方法来创建一个类
class MyClass: pass # 等价于 MyClass = type('MyClass', (), { })
使用上述代码创建一个类,实际上是以下代码的语法糖:
MyClass = type('MyClass', (), { })
3、创建元类的过程
- 因为创建类其实就是执行元类中的
__new__
、__init__
方法,因此要创建自己的元类需要继承type类并通常覆盖__new__
或__init__
方法- new: 创建类对象
- init: 初始化类对象
- prepare: 返回用于类属性初始化的名称空间字典
class MyMeta(type):
@classmethod
def __prepare__(cls, name, bases, **kwargs):
"""在类创建前准备命名空间
返回一个用于存储类属性的字典-like对象
"""
print(f"1. __prepare__: 准备 {
name} 的命名空间")
# 这里使用普通字典,但可以返回自定义的字典子类
# 例如 OrderedDict 保持属性顺序
return {
'__annotations__': {
}}
def __new__(mcls, name, bases, namespace, **kwargs):
"""实际创建类对象
可以修改类的属性或基类
"""
print(f"2. __new__: 创建 {
name} 类对象")
# 自动添加类创建时间戳
namespace['created_at'] = '2023-11-01'
# 强制添加前缀到非魔术方法属性名
new_namespace = {
f'custom_{
k}' if not k.startswith('__') else k: v
for k, v in namespace.items()