[python]元类

最近工作中,一直可以看到元类的代码,之前使用的较少,现做笔记来彻底搞清元类的概念

1 什么是元类

在 Python 中,元类(Metaclass)是一个高级且复杂的概念,它涉及到 Python 的对象模型和类的创建机制。
换句话说,元类控制类的创建,跟类与实例的关系类似。
类和实例的关系:类是实例的模板,通过类可以创建实例。
元类和类的关系:元类是类的模板,通过元类可以创建类。

2 默认的元类

type 是一个内置的元类,它负责创建所有的类。例如:

class MyClass:
    pass

print(type(MyClass))  # 输出:<class 'type'>

3 如何定义元类

元类本质上是一个类,但它必须继承自 type。以下是一个简单的元类示例:

class MyMeta(type):
    def __new__(cls, name, bases, dct):
        # 在类被创建之前,可以修改类的属性和方法
        dct['new_attribute'] = 'This is a new attribute'
        return super().__new__(cls, name, bases, dct)

class MyClass(metaclass=MyMeta):
    pass

print(hasattr(MyClass, 'new_attribute'))  # 输出:True
print(MyClass.new_attribute)  # 输出:This is a new attribute

4 元类的关键方法

__new__ 方法:在类被创建之前调用,用于创建类对象。它接收以下参数:
  cls:元类本身。
  name:类的名称。
  bases:类的基类元组。
  dct:包含类的属性和方法的字典。
__init__ 方法:在类被创建之后调用,用于初始化类对象。它接收与 __new__ 相同的参数。
__call__ 方法:当类被实例化时调用,用于控制类的实例化过程

5 元类的使用场景

5.1 自动添加属性或方法

class AutoAddMeta(type):
    def __new__(cls, name, bases, dct):
        dct['auto_added_method'] = lambda self: "This is an auto-added method"
        return super().__new__(cls, name, bases, dct)

class MyClass(metaclass=AutoAddMeta):
    pass

obj = MyClass()
print(obj.auto_added_method())  # 输出:This is an auto-added method

5.2 单例模式

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 SingletonClass(metaclass=SingletonMeta):
    pass

obj1 = SingletonClass()
obj2 = SingletonClass()
print(obj1 is obj2)  # 输出:True

5.3 检查类的实现

class InterfaceMeta(type):
    def __new__(cls, name, bases, dct):
        if 'required_method' not in dct:
            raise TypeError(f"Class {name} must implement 'required_method'")
        return super().__new__(cls, name, bases, dct)

class MyClass(metaclass=InterfaceMeta):
    def required_method(self):
        return "Implemented method"

# 下面的代码会报错,因为没有实现 required_method
# class MyIncompleteClass(metaclass=InterfaceMeta):
#     pass

5.4 动态修改类的继承关系

假设我们有两个基类 BaseClass1 和 BaseClass2,我们希望在类创建时动态地选择其中一个作为父类。

class BaseClass1:
    def method(self):
        return "Method from BaseClass1"

class BaseClass2:
    def method(self):
        return "Method from BaseClass2"

class DynamicMeta(type):
    def __new__(cls, name, bases, dct):
        # 动态修改 bases 参数
        if name == "MyClass1":
            bases = (BaseClass1,)  # 将 BaseClass1 设置为父类
        elif name == "MyClass2":
            bases = (BaseClass2,)  # 将 BaseClass2 设置为父类
        return super().__new__(cls, name, bases, dct)

# 使用 DynamicMeta 作为元类
class MyClass1(metaclass=DynamicMeta):
    pass

class MyClass2(metaclass=DynamicMeta):
    pass

# 测试
obj1 = MyClass1()
print(obj1.method())  # 输出:Method from BaseClass1

obj2 = MyClass2()
print(obj2.method())  # 输出:Method from BaseClass2
posted @ 2025-06-20 08:35  harrylearn66666  阅读(13)  评论(0)    收藏  举报