1、概念
在Python中,一切皆对象。你定义的类(即使是内置类型)本身也是一种对象。既然类是对象,那么它们也必然由某个“东西”创建。这个创建类的“东西”就是元类(Metaclass)。
- 元类是创建类的类。普通类定义了实例对象的行为,而元类定义了类的行为。
- 默认情况下,Python中所有的类都是由内置元类type创建的
- class MyClass:
- pass
- print(type(MyClass)) # 输出:<class 'type'>
- print(type(1)) # 输出:<class 'int'>
- print(type("hello")) # 输出:<class 'str'>
复制代码 2、元类的工作原理:类创建过程
当你使用 class关键字定义一个类时,Python在幕后执行了以下几步,只要理解类本身就是元类的实例,就容易理解调用__new__和__init__的时机:
- 收集类定义内容:解析类定义体,获取类名、基类和包含属性/方法的字典。
- 确定元类:检查是否指定了自定义元类(通过metaclass关键字),若无则使用默认的type。
- 执行元类的__new__方法:元类的__new__方法负责创建并返回这个类对象。这是干预类创建、修改类属性(如方法、类变量)的关键阶段。
- 执行元类的__init__方法:元类的__init__方法负责对创建好的类对象进行初始化。
- 将类对象绑定到类名:最终,创建的类对象被赋值给类定义头中的类名。
type函数除了可以查看对象的类型,还可以动态地创建类,其语法如下:- MyClass = type('MyClass', (BaseClass,), {'attribute': value, 'method': my_method})
复制代码 3、定义自定义元类
自定义元类通常通过继承type并重写其__new__或 __init__方法来实现,元类的__new__和 __init__方法在类定义阶段就被调用了
3.1 基本元类结构
- class MyMeta(type):
- """自定义元类,继承自 type"""
-
- def __new__(cls, name, bases, attrs):
- """
- 在类创建时调用
- - cls: 元类本身
- - name: 要创建的类名
- - bases: 父类元组
- - attrs: 类属性字典
- """
- print(f"创建类: {name}")
- print(f"父类: {bases}")
- print(f"属性: {list(attrs.keys())}")
-
- # 必须调用 type.__new__ 来实际创建类
- return super().__new__(cls, name, bases, attrs)
-
- def __init__(self, name, bases, attrs):
- """类初始化时调用"""
- super().__init__(name, bases, attrs)
- print(f"初始化类: {name}")
- # 使用元类
- class MyClass(metaclass=MyMeta):
- x = 42
-
- def method(self):
- return "hello"
- # 输出:
- # 创建类: MyClass
- # 父类: ()
- # 属性: ['__module__', '__qualname__', 'x', 'method']
- # 初始化类: MyClass
复制代码 3.2 修改类定义
元类可以在类创建时修改其属性:- class UpperCaseMeta(type):
- """将类中所有非特殊属性名改为大写"""
-
- def __new__(cls, name, bases, attrs):
- # 过滤出需要修改的属性
- uppercase_attrs = {}
- for attr_name, attr_value in attrs.items():
- if not attr_name.startswith('__'): # 不处理特殊方法
- uppercase_attrs[attr_name.upper()] = attr_value
- else:
- uppercase_attrs[attr_name] = attr_value
-
- return super().__new__(cls, name, bases, uppercase_attrs)
- class MyClass(metaclass=UpperCaseMeta):
- my_attr = "value"
- another_attr = 42
-
- def my_method(self):
- return "original"
- # 测试
- obj = MyClass()
- print(hasattr(obj, 'my_attr')) # False
- print(hasattr(obj, 'MY_ATTR')) # True
- print(hasattr(obj, 'my_method')) # False
- print(hasattr(obj, 'MY_METHOD')) # True
复制代码 4、使用场景
4.1 单例模式实现
由于类是元类的对象,因此实例化对象就类似于普通对象直接加(),就会调用元类的__call__方法- 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 DatabaseConnection(metaclass=SingletonMeta):
- def __init__(self, connection_string):
- self.connection_string = connection_string
- print(f"连接到数据库: {connection_string}")
-
- def query(self, sql):
- return f"执行查询: {sql}"
- # 测试单例
- db1 = DatabaseConnection("mysql://localhost:3306/mydb")
- db2 = DatabaseConnection("mysql://localhost:3306/mydb")
- print(db1 is db2) # True
- print(db1.query("SELECT * FROM users"))
复制代码 4.2 ORM(对象关系映射)框架
- class Field:
- """字段基类"""
- def __init__(self, field_type, required=True, default=None):
- self.field_type = field_type
- self.required = required
- self.default = default
- class CharField(Field):
- def __init__(self, max_length=255, **kwargs):
- super().__init__(str, **kwargs)
- self.max_length = max_length
- class IntegerField(Field):
- def __init__(self, **kwargs):
- super().__init__(int, **kwargs)
- class ModelMeta(type):
- """ORM 元类,用于收集字段信息"""
-
- def __new__(cls, name, bases, attrs):
- # 收集字段信息
- fields = {}
- for attr_name, attr_value in attrs.items():
- if isinstance(attr_value, Field):
- fields[attr_name] = attr_value
- # 从类属性中移除字段,避免干扰实例属性
- attrs[attr_name] = None
-
- # 添加_fields属性保存字段信息
- attrs['_fields'] = fields
-
- return super().__new__(cls, name, bases, attrs)
- class Model(metaclass=ModelMeta):
- """模型基类"""
-
- def __init__(self, **kwargs):
- for field_name, field in self._fields.items():
- value = kwargs.get(field_name, field.default)
- setattr(self, field_name, value)
-
- def validate(self):
- """验证字段值"""
- errors = []
- for field_name, field in self._fields.items():
- value = getattr(self, field_name)
- if value is None and field.required:
- errors.append(f"{field_name} is required")
- elif value is not None and not isinstance(value, field.field_type):
- errors.append(f"{field_name} must be {field.field_type.__name__}")
- return errors
- # 使用元类创建模型,子类的创建会继承父类的元类
- class User(Model):
- name = CharField(max_length=100)
- age = IntegerField(required=False, default=0)
- email = CharField(max_length=255)
- # 测试
- user = User(name="Alice", age=25, email="alice@example.com")
- print(user.name) # Alice
- print(user.age) # 25
- print(user.validate()) # []
- user2 = User(name="Bob")
- print(user2.validate()) # ['email is required']
复制代码 来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除 |